單項鍊表和陣列的最大區別是,陣列在記憶體中的空間是連續的,如果要開闢一個陣列一定要先找到空間大小夠用的連續空間。而連結串列則不同,他的各個節點通過引用指向確定關聯關係。
必須要有的一個頭節點,在連結串列中做的大量操作都需要依賴頭節點。尾節點則沒有next。
public class MonomialLinkedList<T> { // 頭節點 private Node first; // 元素個數 private int size = 1; // 增加元素 public void add(T t) { if (first == null) { first = new Node(t, null); } else { Node temp = first; while (true) { if (temp.next == null) { temp.next = new Node(t, null); size++; break; } temp = temp.next; } } } // 返回元素個數 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) { 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 { Node temp = first; for (int i = 0; i < index; i++) { temp = temp.next; } return temp.item; } } // 在指定位置插入 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, null); newNode.next = first; first = newNode; } else { Node temp = first; for (int i = 0; i < index - 1; i++) { temp = temp.next; } Node newNode = new Node(t, null); newNode.next = temp.next; temp.next = 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 temp = first; for (int i = 0; i < index; i++) { temp = temp.next; } temp.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; } else { Node temp = first; for (int i = 0; i < index - 1; i++) { temp = temp.next; } temp.next = temp.next.next; } size--; } // 返回頭節點 public T getFirst() { return first.item; } // 從尾部獲取 新浪面試題 public T lastGet(int index) { if (index > size) { throw new RuntimeException("連結串列長度為:" + size + ",index為" + (size)); } else if (index <= 0) { throw new RuntimeException("下標不能<0"); } Node temp = first; // 計算輸入下標正著數是第幾個。例如size=3 // index是1其實是獲取最後一個,3-1=2 就獲取下標為2的Node for (int i = 0; i < size - index; i++) { temp = temp.next; } return temp.item; } // 反轉連結串列 騰訊面試題 public void reverse() { if (size == 0 || size == 1) { return; } // 整體思路:建立一個新的節點當作頭節點 // 在迴圈中先臨時儲存下一個元素,用於下一次用。 // 然後將頭節點next給當前元素next // 將當前元素新增到頭節點的next // 最後刪除臨時頭節點,反轉完成 // 老的連結串列A B C // N // N A // N B A // N C B A Node reverseNode = new Node(null, null); Node temp = first; for (int i = 0; i < size; i++) { // 臨時下一個Node Node t = temp.next; temp.next = reverseNode.next; reverseNode.next = temp; temp = t; } // 重置頭節點 first = reverseNode; // 刪除臨時頭節點 remove(0); } // 節點物件 class Node { private T item; private Node next; public Node(T item, Node next) { this.item = item; this.next = next; } @Override public String toString() { return "Node [item=" + item + "]"; } } }