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