Java 自定义双向链表

Posted liuzeyu12a

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 自定义双向链表相关的知识,希望对你有一定的参考价值。

双向链表

LinkedList其实也就是我们在数据结构中的链表,这种数据结构有这样的特性:

分配内存空间不是必须是连续的;
插入、删除操作很快,只要修改前后指针就OK了,时间复杂度为O(1);
访问比较慢,必须得从第一个元素开始遍历,时间复杂度为O(n);
在Java中,LinkedList提供了丰富的方法,可以模拟链式队列,链式堆栈等数据结构,为用户带来了极大的方便,下面我们来自定义一个双向链表(目的了解底层实现原理)

 

自定义节点结构

 1 // 自定义节点结构
 2 class Node {
 3     Node first;
 4     Node last;
 5     Object element;
 6 
 7     public Node(Node first, Node last, Object element) {
 8         super();
 9         this.first = first;
10         this.last = last;
11         this.element = element;
12     }
13 
14     public Node(Node node) {
15         this.element = node;
16         node.first = null;
17         node.last = null;
18     }
19 }

一些常用的方法(代码由我们自定义实现):

Java为我们提供了很多方法:

1、add方法

boolean add(E e):在链表后添加一个元素,如果成功,返回true,否则返回false;
void addFirst(E e):在链表头部插入一个元素;
addLast(E e):在链表尾部添加一个元素;
void add(int index, E element):在指定位置插入一个元素。

 1     public void add(Object obj) {
 2         Node newNode = new Node(obj);
 3         if (first == null) {
 4             // newNode.previous = null;
 5             // newNode.next = null;
 6             first = newNode;
 7             last = newNode;
 8         } else {
 9             newNode.previous = last;
10             newNode.next = null;
11 
12             last.next = newNode;
13             last = newNode;
14         }
15         size++;
16     }

 

2、remove方法

E remove();移除链表中第一个元素;
boolean remove(Object o):移除链表中指定的元素;
E remove(int index):移除链表中指定位置的元素;
E removeFirst():移除链表中第一个元素,与remove类似;
E removeLast():移除链表中最后一个元素;
boolean removeFirstOccurrence(Object o):移除链表中第一次出现所在位置的元素;
boolean removeLastOccurrence(Object o):移除链表中最后一次出现所在位置的元素;

 1 public void remove(int index) {
 2         checkRange(index);
 3 
 4         Node temp = getNode(index);
 5         if (temp != null) {
 6             Node up = temp.previous;
 7             Node down = temp.next;
 8 
 9             if (up != null) // 不是头结点
10             {
11                 up.next = down;
12             }
13             if (index == 0) { // 是头结点
14                 first = down;
15             }
16             if (down != null) { // 不是尾节点时
17                 down.previous = up;
18             }
19             if (index == size - 1) {
20                 last = up;
21             }
22             size--;
23         }
24     }

 

全部代码

package 测试容器;

public class TestLinkList<E> {

    int size;
    Node first;
    Node last;

    public static void main(String[] args) {

        TestLinkList<String> lst = new TestLinkList<>();
        lst.add("haha");
        lst.add("hehe");
        lst.add("xixi");
        System.out.println(lst);
        System.out.println(lst.get(0));
        lst.remove(0);
        System.out.println(lst);

    }

    public void add(Object obj) {
        Node newNode = new Node(obj);
        if (first == null) {
            // newNode.previous = null;
            // newNode.next = null;
            first = newNode;
            last = newNode;
        } else {
            newNode.previous = last;
            newNode.next = null;

            last.next = newNode;
            last = newNode;
        }
        size++;
    }

    public void remove(int index) {
        checkRange(index);

        Node temp = getNode(index);
        if (temp != null) {
            Node up = temp.previous;
            Node down = temp.next;

            if (up != null) // 不是头结点
            {
                up.next = down;
            }
            if (index == 0) { // 是头结点
                first = down;
            }
            if (down != null) { // 不是尾节点时
                down.previous = up;
            }
            if (index == size - 1) {
                last = up;
            }
            size--;
        }
    }

    public E get(int index) {
        checkRange(index);

        Node temp = getNode(index);
        return (E) temp.element;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("[");
        Node temp = first;
        while (temp != null) {
            sb.append(temp.element + ",");
            temp = temp.next;
        }
        sb.setCharAt(sb.length() - 1, ]);
        return sb.toString();
    }

    public Node getNode(int index) {
        Node temp = null;
        if (index > (size >> 1)) { // 二分,提高效率
            temp = last;
            for (int i = size - 1; i > index; i--) {
                temp = temp.previous;
            }
        } else {
            temp = first;
            for (int i = 0; i < index; i++) {
                temp = temp.next;
            }
        }
        return temp;
    }

    public void checkRange(int index) {
        if (index < 0 || index > size - 1) {
            throw new RuntimeException("非法索引" + index);
        }

    }
}

// 自定义节点结构
class Node {
    Node previous;
    Node next;
    Object element;

    public Node(Node first, Node last, Object element) {
        super();
        this.previous = first;
        this.next = last;
        this.element = element;
    }

    public Node(Object obj) {
        this.element = obj;
    }
}

 

可以参考单链表的实现过程

参考资料:https://blog.csdn.net/sinat_36246371/article/details/53709625

 

以上是关于Java 自定义双向链表的主要内容,如果未能解决你的问题,请参考以下文章

Java:双向链表反转实现

数据结构与算法-自定义双向链表API

Java 剑指offer(36) 二叉搜索树与双向链表

Java实现双向链表的基本操作

双向链表JAVA代码

Java 集合深入理解 :LinkedList链表源码研究,及双向队列如何实现