Java版-數據結構-鏈表

概要

以前咱們分別學習瞭解了動態數組、棧、隊列,其實他們的底層都是依託靜態數組來實現的、只是經過咱們定義的resize方法來動態擴容解決固定容量的問題,那麼咱們即將學習的鏈表,它實際上是一種真正的動態數據結構。java

介紹

鏈表是一種最簡單的動態數據結構,它可以輔助組成其它的數據結構,鏈表中的元素可存儲在內存中的任何地方(不須要連續的內存,這一點和咱們的數組具備很大的區別,數組須要連續的內存),鏈表中的每一個元素都存儲了下一個元素的地址,從而使一系列隨機的內存地址串接在一塊兒node

存儲鏈表的數據的咱們通常稱爲節點(Node),節點通常分爲兩部分,一部分存儲咱們真正的數據,而另一部分存儲的是下一個節點的引用地址。git

class Node{
    private E e; // 存儲的真正元素
    private Node next;  // 存儲下一個node的引用地址(指向下一個node)
}
複製代碼

好比如今咱們將元素A、B、C三個節點添加到鏈表中,示意圖以下:github

image-20190327213801994

從圖中節點A到節點B之間的箭頭表明,節點A指向了節點BNodeA.next = NodeB),由於在實際業務中咱們的鏈表長度不多是無窮無盡的,基本上都是有限個節點,一般定義鏈表中的最後一個元素它的next存儲的是NULL(空),換句話說,若是在鏈表中,一個節點的next是空(NULL)的話,那麼它必定是最後一個節點(對應咱們圖中的C節點)。數組

根據咱們上面介紹的鏈表基本結構,下面咱們用代碼定義一下鏈表的基本骨架(這裏咱們引入了一個虛擬的頭結點,下面咱們會做說明)數據結構

public class LinkedList<E> {
    /** * 虛擬的頭結點 */
    private Node dummyHead;
    /** * 鏈表中節點的個數 */
    private int size;

    public LinkedList() {
        // 建立一個虛擬的頭結點
        dummyHead = new Node();
    }


    // 節點定義
    private class Node {
        // 存儲節點的元素
        public E e;
        // 存儲下一個節點的地址
        public Node next;

        public Node() {

        }

        public Node(E e) {
            this.e = e;
        }

        public Node(E e, Node next) {
            this.e = e;
            this.next = next;
        }

        @Override
        public String toString() {
            return "Node{" +
                    "e=" + e +
                    ", next=" + next +
                    '}';
        }
    }
}
複製代碼

後面咱們對鏈表的添加節點、刪除節點以及查詢節點,代碼實現都會基於這個基本骨架ide

向鏈表中添加節點

思路分析:

通常咱們向鏈表中添加節點,基本思路:找到添加節點位置的前一個節點preNode,而後再改變鏈表的地址引用;因爲鏈表的第一個節點也就是頭結點沒有前節點,此時咱們爲了操做方便,爲鏈表新增了不存儲任何元素的一個虛擬的頭結點dummyHead(不是必須的,對用戶來說是不可見的),其實鏈表中真正的第一個節點是節點AdummyHead.next),這樣咱們就能保證了,鏈表中存儲元素的節點都有前一個節點。學習

image-20190328144225867

下面咱們來看一下,若是如今有一個節點D,咱們準備把它插入到節點B的位置,咱們須要作哪些操做this

第一步:咱們首先要找到節點B的前一個節點,也就是節點Aspa

第二步:將新節點D的指向指到節點BNodeD.next = NodeA.next),而後再將節點A的指向,指到節點DNodeA.next = NodeD),這樣咱們的節點就能串接起來了

image-20190330090951086

代碼實現:
/** * 向鏈表中指定位置插入節點(學習使用,真正插入不會指定索引) * * @param index 索引的位置 * @param e 節點元素 */
public void add(int index, E e) {
    if (index < 0 || index > size) {
        throw new IllegalArgumentException("不是有效的索引");
    }

    Node prev = dummyHead;

    // 找到index位置的前一個節點
    for (int i = 0; i < index; i++) {
        prev = prev.next;
    }

    // 新建一個節點,進行掛接
    Node node = new Node(e);
    node.next = prev.next;
    prev.next = node;

    size++;
}
複製代碼

鏈表的遍歷

進行鏈表遍歷,咱們須要從鏈表中真正的第一個元素開始,也就是dummyHead.next

/** * 獲取鏈表中index位置的元素 * * @param index 索引的位置 * @return 節點的元素 */
public E get(int index) {
    if (index < 0 || index > size) {
        throw new IllegalArgumentException("不是有效的索引");
    }
    Node cur = dummyHead.next;
    for (int i = 0; i < index; i++) {
        cur = cur.next;
    }
    return cur.e;
}
複製代碼

修改鏈表中元素

/** * 修改鏈表中index位置節點的元素 * * @param index 索引的位置 * @param e 節點的元素 */
public void set(int index, E e) {
    if (index < 0 || index > size) {
        throw new IllegalArgumentException("不是有效的索引");
    }
    Node cur = dummyHead.next;
    for (int i = 0; i < index; i++) {
        cur = cur.next;
    }
    cur.e = e;
}
複製代碼

查找鏈表中是否包含某元素

/** * 查找鏈表中是否包含元素e * * @param e * @return */
public boolean contains(E e) {
    Node cur = dummyHead.next;
    while (cur != null) {
        if (cur.e.equals(e)) {
            return true;
        }
        cur = cur.next;
    }
    return false;
}
複製代碼

刪除鏈表中的元素

image-20190330093907204

在鏈表中刪除元素,與在鏈表中添加元素有點相似

第一步:咱們首先找到刪除節點位置的前一個節點,咱們用prev表示,被刪除的節點咱們用delNode表示

第二步:改變鏈表的引用地址:prev.next = delNode.next(等同於,將節點在鏈表中刪除)

/** * 刪除鏈表中index位置的節點 * * @param index */
public void remove(int index) {
    if (index < 0 || index > size) {
        throw new IllegalArgumentException("不是有效的索引");
    }

    Node prev = dummyHead;

    for (int i = 0; i < index; i++) {
        prev = prev.next;
    }

    Node delNode = prev.next;
    prev.next = delNode.next;
    delNode.next = null;
    size--;
}
複製代碼

完整版代碼GitHub倉庫地址:Java版數據結構-鏈表 歡迎你們【關注】和【Star

至此筆者已經爲你們帶來了數據結構:靜態數組、動態數組、棧、數組隊列、循環隊列、鏈表;接下來,筆者還會一一的實現其它常見的數組結構,你們一塊兒加油!

  • 靜態數組
  • 動態數組
  • 數組隊列
  • 循環隊列
  • 鏈表
  • 循環鏈表
  • 二分搜索樹
  • 優先隊列
  • 線段樹
  • 字典樹
  • AVL
  • 紅黑樹
  • 哈希表
  • ....

持續更新中,歡迎你們關注公衆號:小白程序之路(whiteontheroad),第一時間獲取最新信息!!!

小白程序之路

筆者博客地址:http:www.gulj.cn
相關文章
相關標籤/搜索