双向链表的基本操作: java语言实现

1 双向链表的简单介绍

前不久,写了一篇关于博文《单向链表的基本操作: java语言实现》,现在写一下双向链表的基本操作。与单向链表相比,双向链表多了一个前驱指针域。具体表示结构如下:

previous域--存放结点的直接前驱的地址(位置)的指针域

data域--存放结点值的数据域

next域--存放结点的直接后继的地址(位置)的指针域

双向链表的主要优点是对于任意给的结点,都可以很轻易的获取其前结点和后结点,其主要缺点是每个结点需要保存next和previous两个指针域,因此需要更多的空间开销,同时结点的插入与删除操作也将更加耗时,因为需要操作更多的指向操作。

2 双向链表的基本操作

2.1 创建结点类

//创建一个双向链表结点类,并用get,set方法获取其数据。
public class DLLNode {
    private int data;//数据域
    private DLLNode next;//后继指针域
    private DLLNode previous;//前驱指针域

    public DLLNode(int data) {
        this.data = data;
        this.next = null;
        this.previous = null;
    }

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }

    public DLLNode getNext() {
        return next;
    }

    public void setNext(DLLNode next) {
        this.next = next;
    }

    public DLLNode getPrevious() {
        return previous;
    }

    public void setPrevious(DLLNode previous) {
        this.previous = previous;
    }
    //显示该结点的数据
    public void display() {
        System.out.print( data + " ");
    }
}

2.2 创建链表类

public class DoublyLinkedList {
    private DLLNode head;//表头
    private int length = 0;

    public DoublyLinkedList() {
        this.head = null;
    }

    //在链表头部添加结点
    public void addHead(int data) {
        DLLNode newNode = new DLLNode(data);
        if(head == null) {
            head = newNode;//如果链表为空,增加新结点
        }
        else {
            newNode.setNext(head);
            head.setPrevious(newNode);
            head = newNode;
        }
        length++;
    }

    //在链表头部删除结点
    public void deleteHead() {
        if(head == null){
            System.out.println("空表,删除的结点不存在");
        }
        else {
            DLLNode curNode = head;
            head = curNode.getNext();
            head.setPrevious(null);
        }
        length--;
    }

    //在链表尾部添加结点
    public void addTail(int data) {
        DLLNode newNode = new DLLNode(data);
        if (head == null) {
            head = newNode;
        } else {
            DLLNode curNode = head;
            int count = 1;
            while (count < length) {
                curNode = curNode.getNext();
                count++;
            }
            newNode.setNext(null);
            newNode.setPrevious(curNode);
            curNode.setNext(newNode);
        }
        length++;
    }

    //在链表尾部删除结点
    public void deleteTail() {
        if(head == null){
            System.out.println("空表,删除的结点不存在");
        }else{
            DLLNode preNode = head;
            int count = 1;
            while(count < length-1) {
                preNode = preNode.getNext();
                count++;
            }
            preNode.setNext(null);
        }
        length--;
    }

    //正向遍历链表
    public void printOrderNode() {
        if(head == null) {
            System.out.println("空表");
        }
        DLLNode curNode = head;
        while (curNode != null) {
            curNode.display();
            curNode = curNode.getNext();
        }
        System.out.println();
    }

    //反向遍历链表
    public void printReverseNode() {
        if(head == null) {
            System.out.println("空表");
        }
        DLLNode curNode = head;
        while (curNode.getNext() != null) {
            curNode = curNode.getNext();
        }
        while (curNode != null) {
            curNode.display();
            curNode = curNode.getPrevious();
        }
        System.out.println();
    }

    //获取链表的长度
    public int listLength() {
        return length;
    }

    //在指定位置插入结点
    public void insertList(int data, int index) {
        DLLNode newNode = new DLLNode(data);
        if(head == null){
            head = newNode;//链表为空,插入
        }
        if(index > length+1 || index < 1) {
            System.out.println("结点插入的位置不存在,可插入的位置为1到"+(length+1));
        }
        if(index == 1) {
            newNode.setNext(head);
            head.setPrevious(newNode);
            head = newNode;//在链表开头插入
        } else{              //在链表中间或尾部插入
            DLLNode preNode = head;
            int count = 1;
            while(count < index-1) {
                preNode = preNode.getNext();
                count++;
            }
            DLLNode curNode = preNode.getNext();
            newNode.setNext(curNode);
            newNode.setPrevious(preNode);
            preNode.setNext(newNode);
            if(curNode != null) {
                curNode.setPrevious(newNode);
            }
        }
        length++;
    }

    //在指定位置删除结点
    public void deleteList(int index) {
        if(index > length || index < 1) {
            System.out.println("结点删除的位置不存在,可删除的位置为1到"+length);
        }
        if(index == 1) {
            DLLNode curNode = head;
            head = curNode.getNext();
            head.setPrevious(null);
            length--;
        } else{
            DLLNode preNode = head;
            int count = 1;
            while(count < index-1) {
                preNode = preNode.getNext();
                count++;
            }
            DLLNode curNode = preNode.getNext();
            DLLNode laterNode = curNode.getNext();
            preNode.setNext(laterNode);
            if(laterNode != null) {  //若被删除结点的后继结点不是null结点,那么设置其前驱结点
                laterNode.setPrevious(preNode);//指针指向被删除结点的前驱结点
            }
            length--;
        }
    }

    //查找数据是否存在,与单链表一样
    public boolean containData(int data) {
        if(head == null){
            System.out.println("空表");
            return false;
        }
        DLLNode curNode = head;
        while(curNode.getData()!= data){
            if(curNode.getNext() == null) {
                System.out.println("结点数据不存在");
                return false;
            }
            curNode =curNode.getNext();
        }
        System.out.println("结点数据存在");
        return true;
    }

    //获取指定位置的数据,与单链表一样
    public void getIndexData(int index) {
        if(head == null){
            System.out.println("空表");
        }
        if(index > length || index < 1) {
            System.out.println("结点位置不存在,可获取的位置为1到"+length);
        }
        DLLNode curNode = head;
        int count =1;
        while(count != index) {
            curNode =curNode.getNext();
            count++;
        }
        curNode.display();
        System.out.println();
    }

    //修改指定位置的结点数据,与单链表一样
    public void updateIndexData(int index, int data) {
        if(head == null){
            System.out.println("空表");
        }
        if(index > length || index < 1) {
            System.out.println("结点位置不存在,可更新的位置为1到"+length);
        }
        DLLNode curNode = head;
        int count =1;//while也可以用for循环方式解决
        while(count != index) {
            curNode =curNode.getNext();
            count++;
        }
        curNode.setData(data);
    }
}

3 建立测试类

测试类建立如下,运行结果这里不再赘述。

public class DoublyLinkedListTest {
    public static void main(String [] args) {
        DoublyLinkedList list = new DoublyLinkedList();
        list.addHead(3);
        list.addHead(2);
        list.addHead(1);
        //list.addTail(4);
        //list.addTail(5);
        //list.addTail(6);
        //list.deleteTail();
        //list.deleteHead();
        //list.insertList(1,1);
        //list.deleteList(2);
        //list.containData(1);
        //list.getIndexData(2);
        list.updateIndexData(3,5);
        list.printOrderNode();
        list.printReverseNode();
    }
}

4 个人总结

       对于链表特点及增、删等操作过程及原理的掌握,有助于我们写程序实现。

5 参考资料

[1] 数据结构与算法经典问题解析

[2] 单向链表的基本操作: java语言实现


猜你喜欢

转载自blog.csdn.net/cqulun123/article/details/80261462