鏈表:單鏈表與雙鏈表的區別,初學者一看就會

想象一下,你正在開發一個簡單的遊戲,需要存儲玩家的角色列表,比如從1號玩家到100號玩家。如果用數組來存,刪除中間某個玩家時,後面的所有玩家都要往前挪位置,很麻煩。這時候,鏈表就派上用場了——每個玩家的信息(數據)旁邊只需要記住下一個玩家是誰(指針),不需要連續的內存空間,插入刪除只需要改幾個指針,就像調整糖葫蘆的竹籤一樣方便。

什麼是鏈表?

鏈表是一種線性數據結構,每個元素(稱爲“節點”)由兩部分組成:數據域(存具體信息)和指針域(存下一個/前一個節點的地址)。和數組不同,鏈表的節點在內存中不是連續的,就像散落的珠子用線串起來,線就是指針。

單鏈表:只能“單向”走的糖葫蘆串

單鏈表是最簡單的鏈表,每個節點只有一個指針,指向下一個節點。我們可以把它想象成一串糖葫蘆,每顆山楂(節點)只知道下一顆山楂在哪裏,不知道上一顆。

單鏈表的節點結構:

數據 | 指針 → 下一個節點

比如,存儲“玩家1→玩家2→玩家3”的單鏈表:

玩家1數據 | → 玩家2
玩家2數據 | → 玩家3
玩家3數據 | → null(表示結束)

單鏈表怎麼用?

  • 遍歷:只能從第一個節點(頭節點)開始,順着指針一直走到最後一個節點(next爲null)。比如查第5個玩家,必須從頭開始數到第5個。
  • 插入/刪除:要在中間插入一個節點,得先找到“目標節點的前一個節點”,然後修改指針。比如在玩家2和玩家3之間插入玩家4:
    1. 先找到玩家2(原鏈表:玩家1→玩家2→玩家3)
    2. 新建玩家4節點,讓玩家4的指針指向玩家3
    3. 把玩家2的指針從指向玩家3,改爲指向玩家4
    這樣就完成了插入,不需要移動其他節點。

但如果要刪除玩家3,必須先找到玩家2(前驅節點),把玩家2的指針直接指向玩家3的下一個節點(null)。

雙鏈表:能“前後”走的糖葫蘆串

雙鏈表比單鏈表多了一個指針,每個節點不僅知道下一個節點是誰,還知道前一個節點是誰。現在每顆山楂不僅能被下一顆牽着,還能被上一顆牽着,像帶了雙向掛鉤的糖葫蘆。

雙鏈表的節點結構:

前指針 ← 數據 → 後指針

比如,同樣存儲“玩家1→玩家2→玩家3”的雙鏈表:

null ← 玩家1數據 → 玩家2
玩家1 ← 玩家2數據 → 玩家3
玩家2 ← 玩家3數據 → null

雙鏈表怎麼用?

  • 遍歷:可以從任意節點開始,既能向前走(通過prev指針),也能向後走(通過next指針)。比如從玩家2開始,能直接找到玩家1(用prev)或玩家3(用next)。
  • 插入/刪除:在已知節點處插入或刪除時,雙鏈表更方便。比如在玩家2和玩家3之間插入玩家4:
    1. 新建玩家4節點,把玩家4的prev指向玩家2
    2. 把玩家4的next指向玩家3
    3. 把玩家2的next從指向玩家3,改爲指向玩家4
    4. 把玩家3的prev從指向玩家2,改爲指向玩家4
    這樣一步到位,不需要再找“前驅”,因爲玩家2的prev已經是玩家1,玩家4可以直接和前後節點建立聯繫。

單鏈表 vs 雙鏈表:核心區別大總結

對比項 單鏈表 雙鏈表
節點結構 只有一個指針(next) 兩個指針(prev + next)
遍歷方向 只能單向遍歷(從頭到尾) 雙向遍歷(可前可後)
插入/刪除 需要先找到“前驅節點”,修改指針 直接通過prev/next指針操作,更簡單
內存佔用 少一個指針,節省內存 多一個指針,內存佔用稍高
適用場景 簡單單向數據存儲(如隊列) 需要雙向操作(如瀏覽器歷史、雙向鏈表隊列)

爲什麼要學雙鏈表?

如果你的遊戲只需要“從頭到尾”顯示玩家列表,單鏈表足夠。但如果要實現“同時顯示歷史記錄和未來記錄”(比如瀏覽器的前進後退),或者在鏈表中間頻繁插入刪除節點,雙鏈表更靈活。比如在手機通訊錄中,想在已知聯繫人處同時向前和向後添加聯繫人,雙鏈表能快速完成。

總結

  • 單鏈表:像一串糖葫蘆,只能從左到右喫,簡單省空間,適合單向操作。
  • 雙鏈表:像一串帶雙向掛鉤的糖葫蘆,能從左到右也能從右到左喫,功能更全但稍佔內存,適合需要雙向移動的場景。

初學者不用急着記複雜的操作,先記住“指針數量”和“遍歷方向”的區別,以後遇到實際問題(比如實現一個雙向鏈表隊列)再慢慢熟悉細節~

小夜