2020久久超碰欧美精品最新亚洲欧美日韩久久精品,国产福利电影一区二区三区,亚洲欧美日韩一区在线观看,亚洲国产欧美日韩欧美特级,亚洲欧美日韩成人一区久久,欧美日韩精品一区二区三区不卡,国产欧美日韩va另类影音先锋,亚洲欧美日韩久久精品,亚洲欧美日韩国产成人精品影院,亚洲国产欧美日韩精品一区二区三区,欧美日韩国产成人高清视频,日韩久久精品国产免费观看频道,久久人人爽人人爽从片av高清,国产精品综合一区二区

首頁技術文章正文

什么是單向鏈表?單向鏈表基礎操作

更新時間:2023-03-02 來源:黑馬程序員 瀏覽量:

IT培訓班

在計算機科學中,鏈表是數據元素的線性集合,其每個元素都指向下一個元素,元素存儲上并不連續。鏈表可以分為單向鏈表和雙向鏈表。

單向鏈表,每個元素只知道其下一個元素是誰。
單向鏈表

雙向鏈表,每個元素知道其上一個元素和下一個元素。

1677751700126_43.png

循環鏈表,通常的鏈表尾節點 tail 指向的都是 null,而循環鏈表的 tail 指向的是頭節點 head。鏈表內還有一種特殊的節點稱為哨兵(Sentinel)節點,也叫做啞元( Dummy)節點,它不存儲數據,通常用作頭尾,用來簡化邊界判斷。

單向鏈表

根據單向鏈表的定義,首先定義一個存儲 value 和 next 指針的類 Node,和一個描述頭部節點的引用。

public class SinglyLinkedList {
    
    private Node head; // 頭部節點
    
    private static class Node { // 節點類
        int value;
        Node next;

        public Node(int value, Node next) {            this.value = value;
            this.next = next;
        }
    }
}

在上述代碼中Node 定義為內部類,是為了對外隱藏實現細節,沒必要讓類的使用者關心 Node 結構定義為 static 內部類,是因為 Node 不需要與 SinglyLinkedList 實例相關,多個 SinglyLinkedList實例能共用 Node 類定義。下面演示單向鏈表的創建方法

頭部添加(頭插法)

public class SinglyLinkedList {
    // ...
    public void addFirst(int value) {
        this.head = new Node(value, this.head);
    }
}

如果 this.head == null,新增節點指向 null,并作為新的 this.head。如果 this.head != null,新增節點指向原來的 this.head,并作為新的 this.head。注意賦值操作執行順序是從右到左

尾部添加

public class SinglyLinkedList {
    // ...
    private Node findLast() {
        if (this.head == null) {
            return null;
        }
        Node curr;
        for (curr = this.head; curr.next != null; ) {
            curr = curr.next;
        }
        return curr;
    }
    
    public void addLast(int value) {
        Node last = findLast();
        if (last == null) {
            addFirst(value);
            return;
        }
        last.next = new Node(value, null);
    }
}

注意,找最后一個節點,終止條件是 curr.next == null ,分成兩個方法是為了代碼清晰,而且 findLast() 之后還能復用。

尾部添加多個

public class SinglyLinkedList {
    // ...
    public void addLast(int first, int... rest) {
        
        Node sublist = new Node(first, null);
        Node curr = sublist;
        for (int value : rest) {
            curr.next = new Node(value, null);
            curr = curr.next;
        }
        
        Node last = findLast();
        if (last == null) {
            this.head = sublist;
            return;
        }
        last.next = sublist;
    }
}

先串成一串 sublist,再作為一個整體添加。
根據索引獲取

public class SinglyLinkedList {
    // ...
    private Node findNode(int index) {
        int i = 0;
        for (Node curr = this.head; curr != null; curr = curr.next, i++) {
            if (index == i) {
                return curr;
            }
        }
        return null;
    }
    
    private IllegalArgumentException illegalIndex(int index) {
        return new IllegalArgumentException(String.format("index [%d] 不合法%n", index));
    }
    
    public int get(int index) {
        Node node = findNode(index);
        if (node != null) {
            return node.value;
        }
        throw illegalIndex(index);
    }
}

同樣,分方法可以實現復用

插入

public class SinglyLinkedList {
    // ...
    public void insert(int index, int value) {
        if (index == 0) {
            addFirst(value);
            return;
        }
        Node prev = findNode(index - 1); // 找到上一個節點
        if (prev == null) { // 找不到
            throw illegalIndex(index);
        }
        prev.next = new Node(value, prev.next);
    }
}

注意:插入包括下面的刪除,都必須找到上一個節點。

刪除

public class SinglyLinkedList {
    // ...
    public void remove(int index) {
        if (index == 0) {
            if (this.head != null) {
                this.head = this.head.next;
                return;
            } else {
                throw illegalIndex(index);
            }
        }
        Node prev = findNode(index - 1);
        Node curr;
        if (prev != null && (curr = prev.next) != null) {
            prev.next = curr.next;
        } else {
            throw illegalIndex(index);
        }
    }
}

第一個 if 塊對應著 removeFirst 情況,最后一個 if 塊對應著至少得兩個節點的情況,不僅僅判斷上一個節點非空,還要保證當前節點非空。


分享到:
在線咨詢 我要報名
和我們在線交談!