Java实现双向链表

双向链表就是有两个指针域,一个指向前一项,一个指向后一项,单向链表只可以正向遍历,而双向链表不但可以正向遍历,而且可以反向遍历。

数据结构

节点类

    class Entry {
     
        private int data;
        private Entry pre;
        private Entry next;

        public Entry() {
     
            this(0,null,null);
        }
        
        public Entry(int data, Entry pre, Entry next) {
     
            this.data = data;
            this.pre = pre;
            this.next = next;
        }
    }

节点类是双向链表类的内部类

双向链表类

public class DoubleLinkedList {
     
	//头结点
    private Entry head;
    //初始化头结点
    public DoubleLinkedList() {
     
        head = new Entry();
    }
}

头插法

相比于单向链表的头插法,双向链表由于多了指针域,所以维护起来会稍微复杂一点。

插入分为四步
Java实现双向链表_第1张图片
为了避免在修改指针域时出现的混乱,所以我们从要插入的节点node开始修改,先修改node的next域,再修改node的pre域,然后是下一个节点的pre域,head节点的next域。

  1. 修改node的next域,这里包含为null的情况
	node.next = head.next;
  1. 修改node的pre域
	node.pre = head;
  1. 修改下一个节点的pre域,这里需要注意node的next可能为空的情况,避免抛出空指针
	if(node.next != null)
		node.next.pre = node;
  1. 修改head节点的next域
	head.next = node;

看一下代码实现:

    public void insertHead (int data) {
     
        Entry node = new Entry(data, null, null);
        node.next = head.next;
        node.pre = head;
        if(node.next != null) {
     
            node.next.pre = node;
        }
        head.next = node;
    }

因为双向链表不存在丢失节点的问题, 我们也可以交换1,2或者3,4的顺序

可以在初始化的时候就做指针的连接,这样写起来会更简洁一点。

    public void insertHead (int data) {
     
        Entry node = new Entry(data, head, head.next);
        if(node.next != null) {
     
            node.next.pre = node;
        }
        head.next = node;    
    }

尾插法

尾插法的思路和单链表相同,先找到尾结点,然后把新节点插入到尾节点中即可。

    public void insertTail (int data) {
     
        //找到尾节点
        Entry last = head;
        while(last.next != null) {
     
            last = last.next;
        }
        //插入尾结点后面,修改尾结点的next,修改新节点的pre
        last.next = new Entry(data,last,null);
    }
删除节点

在找到待删除节点后,删除节点可以分为两步:
Java实现双向链表_第2张图片

  1. 修改前一个节点的next域
	cur.pre.next = cur.next;
  1. 修改下一个节点的pre域,这里注意下一个节点有可能为null
	if(cur.next != null)
		cur.next.pre = cur.pre;
  1. 为了减轻gc的负担,我们可以把不用的置为null,也就是图上面没有打叉的两条线
	cur.pre = null;
	cur.next = null;

代码实现:

    public void remove (int data) {
     
        //找到待删除节点
        Entry cur = head.next;
        while(cur != null) {
     
            if(cur.data == data) {
     
                //找到进行删除
                cur.pre.next = cur.next;
                if(cur.next != null) {
     
                    cur.next.pre = cur.pre;
                }

                //置空
                cur.pre = null;
                cur.next = null;
                return;
            }
            cur = cur.next;
        }
    }

你可能感兴趣的:(算法与数据结构,双向链表,数据结构,Java)