實現單項鍊表

頂風少年發表於2020-10-06

單項鍊表和陣列的最大區別是,陣列在記憶體中的空間是連續的,如果要開闢一個陣列一定要先找到空間大小夠用的連續空間。而連結串列則不同,他的各個節點通過引用指向確定關聯關係。

必須要有的一個頭節點,在連結串列中做的大量操作都需要依賴頭節點。尾節點則沒有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 + "]";
        }

    }
}
View Code

 

相關文章