單向鏈表由節點組成,每個節點包含:
public class Node {
E data;
Node next;
public Node(E data) {
this.data = data;
}
public Node(E data, Node next) {
this.data = data;
this.next = next;
}
}
public class SinglyLinkedList {
private Node head; // 虛擬頭節點(哨兵),簡化邊界處理
private int size;
public SinglyLinkedList() {
head = new Node<>(null); // 哨兵節點不存儲數據
size = 0;
}
// 獲取長度
public int size() { return size; }
public boolean isEmpty() { return size == 0; }
// 索引合法性檢查
private void checkIndex(int index) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
private void checkIndexForAdd(int index) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
// 獲取 index 位置的前驅節點(哨兵頭節點索引為 -1)
private Node getPrevNode(int index) {
Node prev = head;
for (int i = -1; i < index; i++) {
prev = prev.next;
}
return prev;
}
// 在 index 處插入元素
public void add(int index, E element) {
checkIndexForAdd(index);
Node prev = getPrevNode(index - 1);
prev.next = new Node<>(element, prev.next);
size++;
}
// 尾部新增
public void add(E element) {
add(size, element);
}
// 獲取 index 位置元素
public E get(int index) {
checkIndex(index);
return getPrevNode(index).next.data;
}
// 設置 index 位置元素
public E set(int index, E element) {
checkIndex(index);
Node node = getPrevNode(index).next;
E old = node.data;
node.data = element;
return old;
}
// 刪除 index 位置元素
public E remove(int index) {
checkIndex(index);
Node prev = getPrevNode(index - 1);
Node removed = prev.next;
prev.next = removed.next;
removed.next = null; // 幫助 GC
size--;
return removed.data;
}
// 查找元素首次出現索引
public int indexOf(E element) {
Node cur = head.next;
for (int i = 0; i < size; i++) {
if (Objects.equals(element, cur.data)) return i;
cur = cur.next;
}
return -1;
}
// 清空
public void clear() {
head.next = null;
size = 0;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
Node cur = head.next;
while (cur != null) {
sb.append(cur.data);
if (cur.next != null) sb.append(", ");
cur = cur.next;
}
sb.append(']');
return sb.toString();
}
}
public class LinkedListTest {
public static void main(String[] args) {
SinglyLinkedList list = new SinglyLinkedList<>();
// 新增測試
list.add(10);
list.add(20);
list.add(30);
list.add(1, 15); // [10, 15, 20, 30]
System.out.println("插入後: " + list);
// 獲取測試
System.out.println("索引 2: " + list.get(2)); // 20
// 修改測試
list.set(1, 99); // [10, 99, 20, 30]
System.out.println("修改後: " + list);
// 刪除測試
list.remove(2); // [10, 99, 30]
System.out.println("刪除後: " + list);
// 查找測試
System.out.println("99 索引: " + list.indexOf(99)); // 1
System.out.println("100 索引: " + list.indexOf(100)); // -1
// 邊界測試
list.add(0, 1); // 頭部插入
list.add(list.size(), 999); // 尾部插入
System.out.println("邊界插入: " + list);
}
}
// 遞歸反轉
public void reverse() {
head.next = reverseRecursive(head.next);
}
private Node reverseRecursive(Node node) {
if (node == null || node.next == null) return node;
Node newHead = reverseRecursive(node.next);
node.next.next = node;
node.next = null;
return newHead;
}
| 操作 | ArrayList | LinkedList |
|---|---|---|
| 隨機存取 get(i) | O(1) ⭐ | O(n) |
| 頭部插入/刪除 | O(n) | O(1) ⭐ |
| 尾部插入/刪除 | O(1) 擴容均攤 | O(1) ⭐ |
| 中間插入/刪除 | O(n) 移動元素 | O(n) 定位 + O(1) 操作 |
| 記憶體開銷 | 低(連續陣列) | 高(節點對象 + 引用) |
| 緩存友好度 | 極高 | 低 |