2010_線性表之連結串列之雙向連結串列
阿新 • • 發佈:2020-09-19
2.2.2 雙向連結串列
2.2.2.1 API設計
類名 Node
構造器 Node(T t, Node pre, Node next)
成員變數 T item;儲存資料
Node next;指向下一個結點
Node pre;指向上一個結點
雙向連結串列API與單向連結串列一致, 新增如下方法
public T getFirst()獲取第一個元素
public T getLast();獲取最後一個元素
2.2.2.2 程式碼實現
package b_linear.b_linkedlist; import java.util.Iterator; public class TwoWayLinkList<T> implements Iterable{ //成員變數 private Node<T> head; private Node<T> last; private int n; //成員內部類 private class Node<T> { //成員變數: 儲存元素 public T item; //下一個結點 public Node next; public Node pre; public Node(T item, Node pre, Node next) { this.item = item; this.pre = pre; this.next = next; } } //構造器 public TwoWayLinkList() { //初始化頭結點 this.head = new Node(null, null, null); //初始化尾結點 this.last = null; //初始化元素個數 this.n = 0; } //成員方法 //清空 public void clear() { this.head.next = null; this.last = null; this.n = 0; } //獲取長度,即元素個數 public int length() { return this.n; } //是否為空 public boolean isEmpty() { return this.n == 0; } //獲取第一個元素 public T getFirst() { if (isEmpty()) { return null; } return (T) this.head.next.item; } //獲取最後一個元素 public T getLast() { if (isEmpty()) { return null; } return this.last.item; } //獲取元素 public T get(int i) { //通過迴圈, 從頭結點開始往後, 依次找到i位置 Node<T> node = head.next; for (int index = 0; index < i; index++) { node = node.next; } return node.item; } //新增元素 public void insert(T t) { //如果連結串列為空 if (isEmpty()) { //建立新結點 Node newNode = new Node(t, head, null); //新結點成為尾結點 last = newNode; //頭結點指向尾結點 head.next = last; } else { //如果不為空 Node oldLast = last; //建立新結點 Node newNode = new Node(t, oldLast, null); //當前尾結點指向尾結點 oldLast.next = newNode; //新結點成為尾結點 last = newNode; } //元素個數加1 this.n++; } //指定位置新增元素 public void insert(int i, T t) { //找到i位置的前一個結點 Node pre = head; for (int index = 0; index < i; index++) { pre = pre.next; } //找到i位置的結點 Node curr = pre.next; //建立新結點 Node newNode = new Node(t, pre, curr); //讓i位置的前結點的下一個結點為新結點 pre.next = newNode; //i位置的前一個結點變為新結點 curr.pre= newNode; //元素個數加 1 this.n++; } //刪除i位置處的元素 public T remove(int i) { //找到i前一個位置的結點 Node<T> pre = head; for (int index = 0; index <= i - 1; index++) { pre = pre.next; } //找到i位置的結節 Node<T> curr = pre.next; //找到i位置下一個結點 Node<T> nextNode = curr.next; //前一個節點指向下一個結點 pre.next = nextNode; //下一個結點指向前一個結點 nextNode.pre = pre; //元素個數一1 this.n--; return curr.item; } //查詢元素首次出現位置 public int indexOf(T t) { //從頭結點開始, 依次找出每一個結點, 取出item與t比較, 如果相迥找到了 Node<T> node = head; for (int i = 0; node.next != null; i++) { node = node.next; if (node.item.equals(t)) { return i; } } return -1; } @Override public Iterator iterator() { return new TIterator(); } private class TIterator implements Iterator { private Node node; public TIterator() { this.node = head; } @Override public boolean hasNext() { return node.next != null; } @Override public Object next() { node = node.next; return node.item; } } }
2.2.2.3 測試
package b_linear.b_linkedlist; /** * 雙向連結串列測試 */ public class TwoWayLinkListTest { public static void main(String[] args) { //建立物件 TwoWayLinkList<String> s1 = new TwoWayLinkList<>(); //插入 s1.insert("姚明"); s1.insert("科比"); s1.insert("麥迪"); s1.insert(1, "詹姆斯"); for(Object s : s1) { System.out.println((String)s); } System.out.println("-----"); System.out.println("第一個: " + s1.getFirst() ); System.out.println("最後一個: " + s1.getLast() ); //獲取 String getResult = s1.get(1); System.out.println(getResult); //刪除 String removeResult = s1.remove(0); System.out.println(removeResult); //清空 s1.clear(); System.out.println("清空後的元素個數: " + s1.length()); } }
2.2.3 連結串列複雜度分析
- get(int i)方法 複雜度為O(n)
- inser(int i, T t); 複雜度為O(n)
- remove(int i); 複雜度為O(n)
增刪有優勢, 初始化時不需要指定長度.
2.2.4 連結串列反轉
-
實現
//連結串列反轉 public void reverse(){ if(isEmpty()) { return; } reverse(head.next); } public Node reverse(Node curr) { if(curr.next == null) { head.next = curr; return curr; } //遞迴反轉curr下一個結點, 返回值為當前結點的上一個結點 Node pre = reverse(curr.next); //返回的結點的下一個結點變為前結點curr pre.next = curr; //當前結點的下一個結點變為null curr.next = null; return curr; }
-
測試
package b_linear.b_linkedlist;
/**
-
單向連結串列測試
*/
public class LinkListTest2 {
public static void main(String[] args) {
//建立物件
LinkLists1 = new LinkList<>();
//插入
s1.insert("姚明");
s1.insert("科比");
s1.insert("麥迪");
s1.insert(1, "詹姆斯");for(Object s : s1) { System.out.println((String)s); } System.out.println("-----"); //反轉 s1.reverse(); for(Object s : s1) { System.out.println((String)s); }
}
}
-
測試結果
姚明
詹姆斯
科比
麥迪
-----
麥迪
科比
詹姆斯
姚明