数据结构笔记(双链表)

目录

前言

一、双链表的定义

二、双链表的实现

1.结点类的定义

2.双链表泛型类的构建

3.双链表的基本算法

1)以头插法整体建立双链表

2)以尾插法整体建立双链表

3)将元素插入i位置

4)双链表的删除操作

三、双链表的应用

总结


前言

链表中的另一种模式是双链表,不同于单链表,双链表的每一个结点都有两个指针成员,一个指向它的前驱节点,一个指向它的后继结点


一、双链表的定义

不同于单链表,双链表的每一个结点都有两个指针成员,一个指向它的前驱节点,一个指向它的后继结点。

二、双链表的实现

1.结点类的定义

与单链表一致,双链表的构架也需要先定义一个双链表结点类

public class DLinkedNode<E> {
    E data;                     //结点所含的数据
    DLinkedNode<E> prior;       //结点的前驱结点
    DLinkedNode<E> next;        //结点的后继结点
    public DLinkedNode(){       //重写无参构造函数
        prior = null;
        next = null;
    }
    public DLinkedNode(E data){ //带参数的构造函数
        this.data = data;
        prior = null;
        next = null;
    }
}

2.双链表泛型类的构建

在定义完结点类之后,就可以开始构造双链表类了

public class DLinkedListClass<E> {
    DLinkedNode<E> dHead;
    public DLinkedListClass(){
        dHead = new DLinkedNode<E>();  //双链表头结点
        dHead.prior = null;            //初始化空的双链表
        dHead.next = null;
    }
}

3.双链表的基本算法

双链表的许多算法与单链表中的相同,如求长度,取值,查找元素等。只有涉及插入和删除的方法不一致。插入结点的操作如下图

数据结构笔记(双链表)

1)以头插法整体建立双链表

在知道了如何插入结点,我们就可以整体建立双链表了,建立的思路与单链表一致

    /**
     * 头插法,得到的双链表与原数组顺序相反
     * @param arr
     */
    public void creatDListFirst(E[] arr){
        DLinkedNode dataNode;
        for (int i=0;i<arr.length;i++){
            dataNode = new DLinkedNode<E>(arr[i]);
            dataNode.next = dHead.next;        //如图中的步骤1
            if(dHead.next!=null){              //双链表需要判断,因为null是没有前驱结点的
                dHead.next.prior = dataNode;   //如图中的步骤2
            }
            dataNode.prior = dHead;            //如图中的步骤3
            dHead.next = dataNode;             //如图中的步骤4
        }
    }

2)以尾插法整体建立双链表

    /**
     * 尾插法,得到的双链表与原数组顺序一致
     * @param arr
     */
    public void creatDListLast(E[] arr){
        DLinkedNode<E> dataNode;
        DLinkedNode<E> pointer = dHead;
        for (int i = 0; i < arr.length; i++) {
            dataNode = new DLinkedNode<E>(arr[i]);
            dataNode.prior = pointer;    //将pointer设为dataNode的前驱结点
            pointer.next = dataNode;     //将dataNode设为pointer和后继结点
            pointer = dataNode;          //将指针移到pointer上,即尾结点
        }
        pointer.next = null;             //将尾结点的后继结点设为null
    }

3)将元素插入i位置

与单链表一致,双链表在插入时也需要获取前一位元素,我们通过getI(i-1)的方式获取

    /**
     * 在第i号位置插入数据E
     * @param i
     * @param data
     */
    public void insert(int i,E data){
        DLinkedNode<E> dataNode = new DLinkedNode<E>(data);
        DLinkedNode<E> pointer = getI(i-1);         //获取前一位元素
        dataNode.next = pointer.next;                  //如图中步骤1
        if(pointer.next!=null) {                       //双链表需要判断,因为null是没有前驱结点的
            pointer.next.prior = dataNode;             //如图中步骤2
        }
        dataNode.prior = pointer;                      //如图中步骤3
        pointer.next = dataNode;                       //如图中步骤4
    }

4)双链表的删除操作

跟单链表一样,双链表的删除操作其原理就是将该结点”孤立“,只要将该结点的前驱结点与其后继结点相连,就可以让双链表在不通过该结点的同时正常运作。但与单链表不同的是,双链表不需要找到该结点的前驱结点,因为可以通过pointer.prior直接获取,具体操作如下图

数据结构笔记(双链表)

代码如下

    /**
     * 删除第i位的元素
     * @param i
     */
    public void delete(int i){
        DLinkedNode<E> pointer = getI(i);
        if(pointer.next!=null){
            pointer.next.prior = pointer.prior;
        }
        pointer.prior.next = pointer.next;
    }

三、双链表的应用

删除双链表中第一个值为x的结点。思路很简单,只要指针指到值为x的结点然后进行删除操作即可。代码如下:

    /**
     * 删除双链表中第一个为x的值
     * @param DList
     * @param x
     */
    public static void deleteX(DLinkedListClass<Integer> DList, Integer x){
        DLinkedNode<Integer> pointer = DList.dHead.next;  //创建指针,指向头结点
        while (pointer!=null && pointer.data!=x){         //查找第一个为x的值
            pointer = pointer.next;                       //指针后移
        }
        if(pointer!=null){                                //如果指针未指到尾,表示找到了x
            if(pointer.next!=null){                       //双链表需要判断,因为null是没有前驱结点的
                pointer.next.prior = pointer.prior;
            }
            pointer.prior = pointer.next;
        }
    }

 


总结

双链表中的代码很大一部分跟单链表一致,但需要注意的是,在双链表中,有时需要通过(pointer.next!=null)来判断是否为尾结点,如果是的话,便不能调取pointer.next.prior。

上一篇:双向链表及有关操作(C语言)


下一篇:双链表