双向链表

双向链表

双向链表我们可以从头到尾查找,也可以从尾到头查找。

双向链表图如下:
在这里插入图片描述

1、双向链表结点类

class Node<E>{
    E data;
    Node<E> prev;
    Node<E> next;

    public Node(E data, Node<E> prev, Node<E> next) {
        this.data = data;
        this.prev = prev;
        this.next = next;
    }
}

2、添加到尾结点的方法

public void linkLast(Object e){
        // 用临时变量 last 保存 head 结点
        final Node<Object> last = tail;
        // 创建一个新的结点,让他的 prev 指针指向 last,next 指针指向 null 结点
        final Node<Object> newNode = new Node<>(e, last, null);
        // 让 tail 指向新的结点
        tail = newNode;
        // 如果之前的 last 为空,说明之前链表是空的,让 head 和 tail 同时指向新结点即可
        if (last == null)
            head = newNode;
        else // 如果之前链表不为空,让之前 last 结点的 next 指向新的结点
            last.next = newNode;
        size++;
    }

3、添加到头结点的方法

public void linkFirst(Object e) {
        // 用临时变量 firt 保存 head 结点
        final Node<Object> first = head;
        // 创建一个新的结点,让他的 prev 指针指向 null,next指针指向head结点
        final Node<Object> newNode = new Node<>(e, null, first);
        // 让 head 指向新的结点
        head = newNode;
        // 如果之前的 first 为空,说明之前链表是空的,让 head 和 tail 同时指向新结点即可
        if (first == null)
            tail = newNode;
        else // 如果之前链表不为空,让之前 first 结点的 prev 指向新的结点
            first.prev = newNode;
        size++;
    }

4、添加到指定结点之前的方法

public void linkBefore(Object e, Node<Object> node) {
        // 用临时变量 nodeprev 保存 node 结点前一个结点
        final Node<Object> nodeprev = node.prev;
        // 创建一个新结点,让他的 prev 指针指向 nodeprev,next 指针指向 node
        final Node<Object> newNode = new Node<>(e, nodeprev, node);
        // 让 node 的 next 指针指向新结点
        node.prev = newNode;
        // 如果之前 node 结点前一个结点为空,说明之前 node 是头结点,让 head 指向新结点
        if (nodeprev == null)
            head = newNode;
        else // 如果之前 node 结点前一个结点不为空,让 node 结点前一个结点指向新结点
            nodeprev.next = newNode;
        size++;
    }

5、删除链表的尾结点的方法

public Object unlinkLast(Node<Object> last) {
        // 用临时变量 element 保存 last 结点的数据
        final Object element = last.data;
        // 创建一个新结点,指向 last 的前一个结点
        final Node<Object> prev = last.prev;
        // 将 last 结点的数据和前一个指针指向 null 
        last.data = null;
        last.prev = null;
        // 尾结点指向 prev
        tail = prev;
        // 如果只有一个结点,把尾结点删除,相当于把链表清空了
        if (prev == null)
            head = null;
        else // 如果不止有一个结点,把 prev 的 next 指向 null
            prev.next = null;
        size--;
        // 返回删除结点的数据
        return element;
    }

6、删除链表的头结点的方法

public Object unlinkFirst(Node<Object> first) {
        // 用临时变量 element 保存 first 结点的数据
        final Object element = first.data;
        // 创建一个新结点,指向 first 的下一个结点
        final Node<Object> nest = first.next;
        // 将 first 结点的数据和下一个指针指向 null
        first.data = null;
        first.next = null;
        // 头结点指向 prev
        head = nest;
        // 如果只有一个结点,把头结点删除,相当于把链表清空了
        if (nest == null)
            tail = null;
        else // 如果不止有一个结点,把 next 的 prev 指向 null
            nest.prev = null;
        size--;
        // 返回删除结点的数据
        return element;
    }

7、删除链表的中间结点的方法

public Object unlink(Node<Object> x) {
        // 用临时变量 element 保存 x 结点的数据
        final Object element = x.data;
        // 创建一个新结点,指向 x 的前一个结点
        final Node<Object> prev = x.prev;
        // 创建一个新结点,指向 x 的下一个结点
        final Node<Object> next = x.next;
        // 前一个结点是空
        if (prev == null) {
            head = next;
        } else { // 前一个结点不为空时,prev 的 next 指针指向 next,将 x 的 prev 置空
            prev.next = next;
            x.prev = null;
        }
        // 后一个结点是空
        if (next == null) {
            tail = null;
        } else { // 后一个结点不为空时,next 的 prev 指针指向 prev,将 x 的 next 置空
            next.prev = prev;
            x.next = null;
        }
        // 将 x 的 data 置空
        x.data = null;
        size--;
        // 返回删除结点的数据
        return element;
    }

完整代码

class Node<E>{
    E data;
    Node<E> prev;
    Node<E> next;

    public Node() {
    }

    public Node(E data, Node<E> prev, Node<E> next) {
        this.data = data;
        this.prev = prev;
        this.next = next;
    }
}
public class MyLinkedList {
    Node<Object> tail = null;
    Node<Object> head = null;
    static int size = 0;

    public MyLinkedList() {
    }

    public MyLinkedList(Node<Object> tail, Node<Object> head) {
        this.tail = tail;
        this.head = head;
    }

    // 添加到尾结点的方法
    public void linkLast(Object e){
        // 用临时变量 last 保存 head 结点
        final Node<Object> last = tail;
        // 创建一个新的结点,让他的 prev 指针指向 last,next 指针指向 null 结点
        final Node<Object> newNode = new Node<>(e, last, null);
        // 让 tail 指向新的结点
        tail = newNode;
        // 如果之前的 last 为空,说明之前链表是空的,让 head 和 tail 同时指向新结点即可
        if (last == null)
            head = newNode;
        else // 如果之前链表不为空,让之前 last 结点的 next 指向新的结点
            last.next = newNode;
        size++;
    }

    // 添加到头结点的方法
    public void linkFirst(Object e) {
        // 用临时变量 firt 保存 head 结点
        final Node<Object> first = head;
        // 创建一个新的结点,让他的 prev 指针指向 null,next 指针指向 head 结点
        final Node<Object> newNode = new Node<>(e, null, first);
        // 让 head 指向新的结点
        head = newNode;
        // 如果之前的 first 为空,说明之前链表是空的,让 head 和 tail 同时指向新结点即可
        if (first == null)
            tail = newNode;
        else // 如果之前链表不为空,让之前 first 结点的 prev 指向新的结点
            first.prev = newNode;
        size++;
    }

    // 添加到指定结点之前的方法
    public void linkBefore(Object e, Node<Object> node) {
        // 用临时变量 nodeprev 保存 node 结点前一个结点
        final Node<Object> nodeprev = node.prev;
        // 创建一个新结点,让他的 prev 指针指向 nodeprev,next 指针指向 node
        final Node<Object> newNode = new Node<>(e, nodeprev, node);
        // 让 node 的 next 指针指向新结点
        node.prev = newNode;
        // 如果之前 node 结点前一个结点为空,说明之前 node 是头结点,让 head 指向新结点
        if (nodeprev == null)
            head = newNode;
        else // 如果之前 node 结点前一个结点不为空,让 node 结点前一个结点指向新结点
            nodeprev.next = newNode;
        size++;
    }

    // 删除链表的尾结点的方法
    public Object unlinkLast(Node<Object> last) {
        // 用临时变量 element 保存 last 结点的数据
        final Object element = last.data;
        // 创建一个新结点,指向 last 的前一个结点
        final Node<Object> prev = last.prev;
        // 将 last 结点的数据和前一个指针指向 null
        last.data = null;
        last.prev = null;
        // 尾结点指向 prev
        tail = prev;
        // 如果只有一个结点,把尾结点删除,相当于把链表清空了
        if (prev == null)
            head = null;
        else // 如果不止有一个结点,把 prev 的 next 指向 null
            prev.next = null;
        size--;
        // 返回删除结点的数据
        return element;
    }

    // 删除链表的头结点的方法
    public Object unlinkFirst(Node<Object> first) {
        // 用临时变量 element 保存 first 结点的数据
        final Object element = first.data;
        // 创建一个新结点,指向 first 的下一个结点
        final Node<Object> nest = first.next;
        // 将 first 结点的数据和下一个指针指向 null
        first.data = null;
        first.next = null;
        // 头结点指向 prev
        head = nest;
        // 如果只有一个结点,把头结点删除,相当于把链表清空了
        if (nest == null)
            tail = null;
        else // 如果不止有一个结点,把 next 的 prev 指向 null
            nest.prev = null;
        size--;
        // 返回删除结点的数据
        return element;
    }

    // 删除链表的中间结点的方法
    public Object unlink(Node<Object> x) {
        // 用临时变量 element 保存 x 结点的数据
        final Object element = x.data;
        // 创建一个新结点,指向 x 的前一个结点
        final Node<Object> prev = x.prev;
        // 创建一个新结点,指向 x 的下一个结点
        final Node<Object> next = x.next;
        // 前一个结点是空
        if (prev == null) {
            head = next;
        } else { // 前一个结点不为空时,prev 的 next 指针指向 next,将 x 的 prev 置空
            prev.next = next;
            x.prev = null;
        }
        // 后一个结点是空
        if (next == null) {
            tail = null;
        } else { // 后一个结点不为空时,next 的 prev 指针指向 prev,将 x 的 next 置空
            next.prev = prev;
            x.next = null;
        }
        // 将 x 的 data 置空
        x.data = null;
        size--;
        // 返回删除结点的数据
        return element;
    }

}

测试一下

public class Test {
    static MyLinkedList myLinkedList = new MyLinkedList();
    public static void main(String[] args) {
        myLinkedList.linkFirst(1);
        show();
        myLinkedList.linkLast(2);
        myLinkedList.linkLast(3);
        show();
        myLinkedList.linkBefore(4, myLinkedList.head);
        show();
        System.out.println("删除链表的中间结点: " + myLinkedList.unlink(myLinkedList.head.next));
        show();
        System.out.println("删除链表的尾结点: " + myLinkedList.unlinkLast(myLinkedList.tail));
        show();
        System.out.println("删除链表的头结点: " + myLinkedList.unlinkFirst(myLinkedList.head));
        show();
    }
    public static void show() {
        Node<Object> node = myLinkedList.head;
        while (node != null) {
            System.out.print(node.data + " ");
            node = node.next;
        }
        System.out.println();
    }
}

运行结果如下

1 
1 2 3 
4 1 2 3 
删除链表的中间结点: 1
4 2 3 
删除链表的尾结点: 3
4 2 
删除链表的头结点: 4
2 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值