雙向連結串列和單向連結串列相比更加靈活,它的每一個元素除了本身的值以為擁有兩個指標,分別指向上一個和下一個節點。維護成本上要高於單向連結串列。連結串列的大部分操作依賴於遍歷,這一方面雙向連結串列會效率會好一些,可以根據查詢下標的位置從而選擇從連結串列頭開始遍歷還是從連結串列尾開始遍歷。
package com.dfsn.cloud.eureka; public class BothwayLinkedList<T> { // 頭節點 private Node first; // 尾節點 private Node last; // 元素個數 private int size = 0; // 增加元素 public void add(T t) { if (first == null) { Node newNode = new Node(t, null, null); first = newNode; last = newNode; } else { Node newLast = new Node(t, null, last); last.next = newLast; last = newLast; } size++; } // 返回元素個數 public int size() { return size; } // 遍歷連結串列 public void show() { if (first == null) { throw new RuntimeException("連結串列為空"); } else { Node temp = first; while (true) { System.out.println(temp); if (temp.next == null) { break; } temp = temp.next; } } } // 根據下標獲取節點 public T get(int index) { return get(index, "").item; } private Node get(int index, String s) { if (first == null) { throw new RuntimeException("連結串列為空,沒有對應節點"); } else if (index >= size) { throw new RuntimeException("連結串列長度為:" + size + ",index為" + (size - 1)); } else if (index < 0) { throw new RuntimeException("下標不能<0"); } else { int avg = size / 2; if (index < avg) { Node temp = first; for (int i = 0; i < index; i++) { temp = temp.next; } return temp; } else { Node temp = last; for (int i = size - 1; i > index; i--) { temp = temp.prev; } return temp; } } } // 在指定位置插入 public void add(int index, T t) { if (index > size) { throw new RuntimeException("連結串列長度為:" + size + ",index為" + size); } else if (index < 0) { throw new RuntimeException("下標不能<0"); } else if (index == 0) { Node newNode = new Node(t, first, null); newNode.next = first; first = newNode; } else if (index == size) { Node newNode = new Node(t, null, last); last.next = newNode; last = newNode; } else { // 原來位置的node Node node = get(index, ""); Node newNode = new Node(t, node, node.prev); node.prev.next = newNode; node.prev = newNode; } size++; } // 更改指定位置的元素 public void set(int index, T t) { if (index >= size) { throw new RuntimeException("連結串列長度為:" + size + ",index為" + (size - 1)); } else if (index < 0) { throw new RuntimeException("下標不能<0"); } else { Node node = get(index, ""); node.item = t; } } // 刪除指定位置的元素 public void remove(int index) { if (index >= size) { throw new RuntimeException("連結串列長度為:" + size + ",index為" + (size - 1)); } else if (index < 0) { throw new RuntimeException("下標不能<0"); } else if (index == 0) { first = first.next; first.prev = null; } else if (index == size - 1) { last = last.prev; last.next = null; } else { Node node = get(index, ""); Node next = node.next; Node prev = node.prev; prev.next = next; next.prev = prev; } size--; } // 返回頭節點 public T getFirst() { return first.item; } // 返回尾節點 public T getLasts() { return last.item; } // 節點物件 class Node { private T item; private Node next; private Node prev; public Node(T item, Node next, Node prev) { this.item = item; this.next = next; this.prev = prev; } @Override public String toString() { return "Node [item=" + item + "]"; } } }