美文网首页
自己动手写数据结构之双向链表

自己动手写数据结构之双向链表

作者: 逍遥白亦 | 来源:发表于2020-12-19 12:10 被阅读0次

    双向链表的实现

    1 定义

    双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表

    2 基本元素

    链表头 First

    链表尾 Last

    节点 Node

    节点中数据域 data

    节点中指针域 next

    节点中指针域 prev

    3 基本操作

    表头插入 insertFirst

    表尾插入 insertLast

    指定特定值的节点之后插入 insertAfter

    表头删除 deleteFirst

    表尾删除 deleteLast

    4 基本思路

    insertFirst

    添加第一个结点时

    头结点和尾结点均指向新结点

    first = newNode

    last = newNode

    添加新结点时

    (1) 头结点指向新结点 first = newNode

    (2) 新结点的next指向原有头结点 newNode.next = first

    (3) 原有头结点的prev指向新结点 first.prev = newNode

    (4) 尾结点指向原头结点,保持不变

    代码实现

        public void insertFirst(int data){
            Node newNode = new Node(data);
            if (isEmpty()){
                last = newNode;
            }else {
                //将原结点的前指针同新结点相连
                first.prev = newNode;
            }
    
            newNode.next = first;
    
            first = newNode;
    
        }
    

    insertLast

    添加第一个结点时

    头结点和尾结点均指向新结点

    first = newNode

    last = newNode

    新结点的prev指向null

    添加新结点时

    (1)头结点不变

    (2)尾结点指向新结点 last = newNode

    (3)原尾结点的next指向新结点 last.next = newNode

    (4)新结点的prev指向原尾结点 newNode.prev = last

    代码实现

    public void insertLast(int data){
            Node newNode = new Node(data);
    
            if (isEmpty()){
                first = newNode;
            }else {
                //将原结点的后指针同新结点相连
                last.next = newNode;
                newNode.prev = last;
            }
            
            last = newNode;
        }
    

    insertAfter

    先找到当前结点

    代码实现

        public Node find(int data){
    
            Node current = first;
    
            while (current.data != data){
                if (current.next == null){
                    return null;
                }else {
                    current = current.next;
                }
            }
    
            return current;
    
        }
    

    要插入结点为最后一个

    (1) 尾结点指向新结点 last = newNode

    (2) 当前结点next指向新结点 current.next = newNode

    (3) 新结点的prev指向当前结点 newNode.prev = current

    (4) 新结点的next指向null newNode.next = null

    要插入结点为中间结点

    (1) 头尾结点保持不变

    (2) 当前结点的next指向指向新结点 current.next = newNode

    (3) 新结点的prev指向当前结点 newNode.prev = current

    (4) 新结点的next指向当前结点的下一结点 newNode.next = current.next

    (5) 当前结点下一结点的prev指向新结点 current.next.prev = newNode

    代码实现

        public void insertAfter(int targetData, int newData){
            Node current = find(targetData);
    
            Node newNode = new Node(newData);
    
            if (current != null){
                if (current == last){
                    last = newNode;
                    newNode.next = null;
                }else {
                    newNode.next = current.next;
                    current.next.prev = newNode;
                }
    
                current.next = newNode;
                newNode.prev = current;
            }
        }
    

    deleteFirst

    只有一个结点

    (1) 头尾结点均为null first,last = null

    有多个结点

    (1) 头结点指向原头结点的下一结点 first = first.next

    (2) 原头结点的下一结点prev为null first.next.prev = null

    代码实现

        public int deleteFirst(){
            int temp = first.data;
            if (first.next == null){
                last = null;
            }else {
                first.next.prev = null;
            }
            first = first.next;
            return temp;
        }
    

    deleteLast

    只有一个结点

    (1) 头尾结点均为null first,last = null

    有多个结点

    (1) 尾结点指向原尾结点的上一结点 last = last.prev

    (2) 原尾结点上一结点的next指向null last.prev.next = null

    代码实现

        public int deleteLast(){
            int temp = first.data;
            if (first.next == null){
                first = null;
            }else {
                last.prev.next = null;
            }
            last = last.prev;
            return temp;
        }
    

    deleteKey

    被删除的是第一个结点

    (1)头结点指向当前结点下一结点 first = current.next

    (2)当前结点下一结点的prev为null,current.next.prev = null 被删除的是最后一个结点

    (1)尾结点指向当前结点上一结点,last = current.prev

    (2)当前结点上一结点的next为null, current.prev.next = null 被删除的是中间结点

    (1) 尾结点指向当前结点下一结点 last = current.next

    (2) 当前结点上一结点的next指向当前结点的下一结点 current.prev.next = current.next

    (3) 当前结点下一结点的prev指向当前结点的上一结点 current.next.prev = current.prev

    代码实现

    public int deleteKey(int data){
            Node current = find(data);
            if (current != null){
                if (current == first){
                    first = current.next;
                }else {
                    current.prev.next = current.next;
                }
    
                if (current == last){
                    last = current.prev;
                }else {
                    current.next.prev = current.prev;
                }
    
                return current.data;
            }
    
            return 0;
        }
    

    相关文章

      网友评论

          本文标题:自己动手写数据结构之双向链表

          本文链接:https://www.haomeiwen.com/subject/hdaqnktx.html