doubly linked list data structure visualization with nodes and bidirectional arrows

Python 資料結構:雙向鏈結串列(Doubly Linked List)(03)

在學習了鏈結串列(Linked List)之後,接下來要進一步認識 雙向鏈結串列(Doubly Linked List)
它是一種能夠同時往前與往後遍歷的資料結構,為許多需要雙向導航的應用場景提供了便利。


什麼是雙向鏈結串列?

雙向鏈結串列與單向鏈結串列相似,都是由一系列節點(Node)組成。但 Doubly Linked List 的節點比單向串列更聰明,因為它除了記錄 下一個節點的連結(next),還會額外儲存 前一個節點的連結(prev)

特性

  • 雙向遍歷:不僅能從頭走到尾,還能從尾回到頭。
  • 頭尾指標:同時維護 headtail,大幅提升操作效率。
  • 靈活操作:能在串列的開頭、結尾,甚至任意位置快速插入或刪除。

doubly linked list data structure visualization with nodes and bidirectional arrows

Node 與 Doubly Linked List 類別

一個 Doubly Linked List 的基本組成包含兩個部分:

  1. Node 類別:保存數值、前一個節點指標(prev)、下一個節點指標(next)。
  2. Doubly Linked List 類別:保存整個串列的頭部(head)與尾部(tail),並提供操作方法。

初始化時,headtail 都會設為 None,代表串列是空的。


核心功能設計

雙向鏈結串列的價值在於它能支援更多、更靈活的操作。以下是實作時常見的核心功能與用途:

1. 新增到頭部(Add to Head)

  • 將新節點插入到串列最前端。
  • 需要同時更新新節點的 next 指向舊 head,並更新舊 head 的 prev
  • 如果原本串列是空的,還要將尾部(tail)一併更新。
  • 用途:適合需要頻繁在開頭新增元素的情境,例如佇列的「快速入隊」。
def add_to_head(self, new_value):
    new_head = Node(new_value)
    current_head = self.head_node
    
    if current_head != None:
        current_head.set_prev_node(new_head)
        new_head.set_next_node(current_head)
    
    self.head_node = new_head
    
    if self.tail_node == None:
        self.tail_node = new_head

adding node to head of doubly linked list diagram

2. 新增到尾部(Add to Tail)

  • 將新節點插入到串列最後端。
  • 由於 DLL 保持 tail 指標,不必遍歷即可完成操作。
  • 需要讓新節點的 prev 指向舊 tail,舊 tail 的 next 指向新節點,最後更新 tail
  • 用途:適合需要快速在末尾插入元素的應用,例如音樂播放清單或工作任務隊列。
def add_to_tail(self, new_value):
    new_tail = Node(new_value)
    current_tail = self.tail_node
    
    if current_tail != None:
        current_tail.set_next_node(new_tail)
        new_tail.set_prev_node(current_tail)
    
    self.tail_node = new_tail
    
    if self.head_node == None:
        self.head_node = new_tail

3. 移除頭部節點(Remove Head)

  • 移除串列最前端的節點,並更新 head 為下一個節點。
  • 若新 head 存在,需將它的 prev 設為 None
  • 如果移除的節點同時也是尾節點(僅一個元素的情況),則需要額外處理 tail。
  • 用途:模擬 FIFO(先進先出)的結構,常見於排程或緩衝區。
def remove_head(self):
    removed_head = self.head_node
    if removed_head == None:
        return None

    self.head_node = removed_head.get_next_node()

    if self.head_node != None:
        self.head_node.set_prev_node(None)
    if removed_head == self.tail_node:
        self.remove_tail()
    return removed_head.get_value()

4. 移除尾部節點(Remove Tail)

  • 移除串列最後端的節點,並更新 tail 為前一個節點。
  • 若新 tail 存在,需將它的 next 設為 None
  • 如果移除的節點同時是 head,則需要額外處理 head。
  • 用途:在 LRU Cache 或瀏覽器歷史記錄中,用來快速丟棄最新或最舊的資料。
def remove_tail(self):
    removed_tail = self.tail_node
    if removed_tail == None:
        return None
   
    self.tail_node = removed_tail.get_prev_node()
   
    if self.tail_node != None:
        self.tail_node.set_next_node(None)
    if removed_tail == self.head_node:
        self.remove_head()
    return removed_tail.get_value()

5. 依值移除節點(Remove by Value)

  • 從頭開始搜尋,找到第一個匹配的節點並刪除。
  • 需要處理三種情況:
    1. 刪除 head:直接呼叫 remove_head()
    2. 刪除 tail:直接呼叫 remove_tail()
    3. 刪除中間節點:更新前後節點的指標,讓它們彼此連接,跳過被刪除的節點。
  • 用途:動態資料管理,例如刪除播放清單中的指定歌曲,或從操作歷史中移除某一步驟。
def remove_by_value(self, value_to_remove):
    current_node = self.head_node
    
    while current_node != None:
        if current_node.get_value() == value_to_remove:
            # 移除頭部
            if current_node == self.head_node:
                return self.remove_head()
            # 移除尾部
            elif current_node == self.tail_node:
                return self.remove_tail()
            else:
                next_node = current_node.get_next_node()
                prev_node = current_node.get_prev_node()
                next_node.set_prev_node(prev_node)
                prev_node.set_next_node(next_node)
                return current_node.get_value()
        current_node = current_node.get_next_node()
    return None

removing middle node from doubly linked list pointer adjustment

實際應用場景

  • 音樂播放器:支援「上一首 / 下一首」功能。
  • 地鐵或公車路線:方便在站點之間前後查詢。
  • 瀏覽器操作歷史:透過雙向鏈結串列管理「復原(Undo)」與「重做(Redo)」。

結語

雙向鏈結串列透過 前後指標的設計,大幅提升了資料結構的靈活性,特別適合需要 雙向導航、快速插入刪除 的場景。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

High Quality

Lorem ipsum dolor sit amet, consectetur adipiscing elitsed do eiusmod tempor.

Fast Delivery

Lorem ipsum dolor sit amet, consectetur adipiscing elitsed do eiusmod tempor.

Best Warranty

Lorem ipsum dolor sit amet, consectetur adipiscing elitsed do eiusmod tempor.