python實現 雙向循環鏈表


最近身邊的朋友在研究用python來實現數據結構。遇到一個問題就是雙向循環鏈表的實現,改指向的時候總是發蒙。

我自己嘗實現了一個python的雙向循環鏈表。附上代碼,希望對大家有幫助。

如果不懂什么是雙向循環鏈表的伙伴,需要補習一下數據結構的基礎之后哦~~~

在python當中 用一個類Node 來實現鏈表的節點,節點數據有三個變量:

  prev:前驅指針: 用於指向當前節點前一個節點

  next: 后繼指針  用於指向當前節點后一個節點

  item: 值, 用於存儲該節點要存的數值

  當前節點的前一個節點我們叫他前驅,后一個節點我們叫他后繼。

在鏈表類當中,我們有一個變量head是鏈表的頭指針

我們拿着鏈表的頭head,就可以對他進行一些列操作:( 由於是雙向循環鏈表,修改指針特別容易出錯,我盡量說的細致,方便大家參考)

判斷空:  is_empty()

  如果頭指針head沒有指向則鏈表是空的 否則不是空的

在頭部添加元素: add(item)

  1 新建一個節點 里面的值是item。

  2 放入頭部:

    2.1 如果鏈表是空的,node的next和prev都指向自己,然后head再指向node

在尾部添加元素: append(item)

  1 創建一個新節點node 里面的值是item

  2 放入尾部:

    2.1 如果鏈表空,則執行頭部添加add就可以

    2.2 鏈表非空:

      2.2.1 node的next指向head

      2.2.2 node的prev指向head的prev

      2.2.3 head的prev元素的next指向node

      2.2.4 head的prev指向改為node

      2.2.5 head指向node  更換了頭部

指定位置添加元素: insert( pos , item )

   1 新建一個節點node 里面的值是item

   2 找到合適的位置插進去:

      2.1 如果pos <= 0 還小,那就執行頭插方法 add()

      2.2 如果pos >= 鏈表長度, 那就執行尾部插入 append()

      2.3 如果pos位置在鏈表的中間:

        2.3.1 定義一個臨時變量temp 按照傳入的pos找到要插入的位置的前一個元素

        2.3.2 node的prev設為temp,node的next設為temp的next

        2.3.3 temp的next指向的節點的prev改為node

        2.3.4 temp的next改為node

得到鏈表長度: length()

   1 我們設置一個臨時變量temp初始設為head , 設置一個計數器count 初始為 0

   2 令count自增1 然后temp改指向自己的下一個元素 一直到temp遇到None 為止,temp到了鏈表的最后一個元素

    通過這樣的方式,統計出一共有多少個節點返回

遍歷鏈表數據: travelji()

   1 設置一個臨時變量temp初始化設為head

   2 temp 每次輸出自己指向元素的值,然后在指向自己的下一個元素,一直temp為None 說明到了列表的尾部

刪除鏈表元素: remove( item )

  1 開啟temp臨時變量 初始化為head , 

  2  temp不斷指向自己的下一個元素,每次指向一個元素都檢查當前值是不是item,如果找到item則刪除它返回True,如果沒找到就到尾部了就返回False

    2.1 刪除過程:

      2.1.1 temp的前一個元素的next改為temp的后一個元素

      2.1.2 temp的后一個元素的prev改為前一個元素

 

查詢是否有元素:search()

  設置一個臨時變量temp從head開始,不斷指向自己下一個,每次都檢查一下自己的值如果和item相同返回True結束

  如果temp變成None 則到尾部了都沒找到 返回False

 

上代碼!

 1 #鏈表的節點
 2 class Node(object):  3     def __init__(self , item ):  4         self.item = item    #節點數值
 5         self.prev = None    #用於指向前一個元素
 6         self.next = None    #用於指向后一個元素
 7 #雙向循環鏈表
 8 class DoubleCircleLinkList(object):  9     def __init__(self):  10         self.__head = None  #初始化的時候頭節點設為空、
 11     #判斷鏈表是否為空,head為None 的話則鏈表是空的
 12     def is_empty(self):  13         return self.__head is None  14     #頭部添加元素的方法
 15     def add(self,item):  16         node = Node(item)   #新建一個節點node 里面的值是item
 17         # 如果鏈表是空的,則node的next和prev都指向自己(因為是雙向循環),head指向node
 18         if self.is_empty():  19             self.__head = node  20             node.next = node  21             node.prev = node  22         # 否則鏈表不空
 23         else:  24             node.next = self.__head #node的next設為現在的head
 25             node.prev = self.__head.prev #node的prev 設為現在head的prev
 26             self.__head.prev.next = node  #現在head的前一個元素的next設為node
 27             self.__head.prev = node #現在head的前驅 改為node
 28             self.__head = node #更改頭部指針
 29     #尾部添加元素方法
 30     def append(self , item):  31         #如果當前鏈表是空的 那就調用頭部插入方法
 32         if self.is_empty():  33  self.add(item)  34         #否則鏈表不為空
 35         else :  36             node = Node(item)   #新建一個節點node
 37             #因為是雙向循環鏈表,所以head的prev其實就是鏈表的尾部
 38             node.next = self.__head #node的下一個設為頭
 39             node.prev = self.__head.prev    #node的前驅設為現在頭部的前驅
 40             self.__head.prev.next = node    #頭部前驅的后繼設為node
 41             self.__head.prev = node #頭部自己的前驅改為node
 42     #獲得鏈表長度 節點個數
 43     def length(self):  44         #如果鏈表是空的 就返回0
 45         if self.is_empty():  46             return 0  47         #如果不是空的
 48         else:  49             cur = self.__head   #臨時變量cur表示當前位置 初始化設為頭head
 50             count = 1   #設一個計數器count,cur每指向一個節點,count就自增1 目前cur指向頭,所以count初始化為1
 51             #如果cur.next不是head,說明cur目前不是最后一個元素,那么count就1,再讓cur后移一位
 52             while cur.next is not self.__head:  53                 count += 1
 54                 cur = cur.next  55             #跳出循環說明所有元素都被累加了一次 返回count就是一共有多少個元素
 56             return count  57     #遍歷鏈表的功能
 58     def travel(self):  59         #如果當前自己是空的,那就不遍歷
 60         if self.is_empty():  61             return
 62         #鏈表不空
 63         else :  64             cur = self.__head   #臨時變量cur表示當前位置,初始化為鏈表的頭部
 65             #只要cur的后繼不是頭說明cur不是最后一個節點,我們就輸出當前值,並讓cur后移一個節點
 66             while cur.next is not self.__head:  67                 print( cur.item,end=" " )  68                 cur = cur.next  69             #當cur的后繼是head的時候跳出循環了,最后一個節點還沒有打印值 在這里打印出來
 70             print( cur.item )  71 
 72     #置頂位置插入節點
 73     def insert(self, pos , item ):  74         #如果位置<=0 則調用頭部插入方法
 75         if pos <= 0:  76  self.add(item)  77         #如果位置是最后一個或者更大 就調用尾部插入方法
 78         elif pos > self.length() - 1 :  79  self.append(item)  80         #否則插入位置就是鏈表中間
 81         else :  82             index = 0   #設置計數器,用於標記我們后移了多少步
 83             cur = self.__head   #cur標記當前所在位置
 84             #讓index每次自增1 ,cur后移,當index=pos-1的時候說明cur在要插入位置的前一個元素,這時候停下
 85             while index < pos - 1 :  86                 index += 1
 87                 cur = cur.next  88             #跳出循環,cur在要插入位置的前一個元素,將node插入到cur的后面
 89             node = Node(item) #新建一個節點
 90             node.next = cur.next    #node的后繼設為cur的后繼
 91             node.prev = cur #node的前驅設為cur
 92             cur.next.prev = node    #cur后繼的前驅改為node
 93             cur.next = node #cur后繼改為node
 94     #刪除節點操作
 95     def remove(self,item):  96         #如果鏈表為空 直接不操作
 97         if self.is_empty():  98             return
 99         #鏈表不為空
100         else: 101             cur = self.__head   #臨時變量標記位置,從頭開始
102             #如果頭結點就是 要刪除的元素
103             if cur.item == item: 104                 #如果只有一個節點 鏈表就空了 head設為None
105                 if self.length() == 1: 106                     self.__head = None 107                 #如果多個元素
108                 else: 109                     self.__head = cur.next #頭指針指向cur的下一個
110                     cur.next.prev= cur.prev #cur后繼的前驅改為cur的前驅
111                     cur.prev.next = cur.next #cur前驅的后繼改為cur的后繼
112             #否則 頭節點不是要刪除的節點 我們要向下遍歷
113             else: 114                 cur = cur.next  #把cur后移一個節點
115                 #循環讓cur后移一直到鏈表尾元素位置,期間如果找得到就刪除節點,找不到就跳出循環,
116                 while cur is not self.__head: 117                     #找到了元素cur就是要刪除的
118                     if cur.item == item: 119                         cur.prev.next = cur.next    #cur的前驅的后繼改為cur的后繼
120                         cur.next.prev = cur.prev    #cur的后繼的前驅改為cur的前驅
121                     cur = cur.next 122     #搜索節點是否存在
123     def search(self , item): 124         #如果鏈表是空的一定不存在
125         if self.is_empty(): 126             return False 127         #否則鏈表不空
128         else: 129             cur = self.__head   #設置臨時cur從頭開始
130             # cur不斷后移,一直到尾節點為止
131             while cur.next is not self.__head: 132                 #如果期間找到了就返回一個True 結束運行
133                 if cur.item == item: 134                     return True 135                 cur = cur.next 136             # 從循環跳出來cur就指向了尾元素 看一下為元素是不是要找的 是就返回True
137             if cur.item ==item: 138                 return True 139             #所有元素都不是 就返回False 沒找到
140             return False 141 
142 
143 if __name__ == "__main__": 144     dlcl = DoubleCircleLinkList() 145     print(dlcl.search(7)) 146  dlcl.travel() 147     dlcl.remove(1) 148     print(dlcl.length()) 149     print(dlcl.is_empty()) 150     dlcl.append(55) 151     print(dlcl.search(55)) 152  dlcl.travel() 153     dlcl.remove(55) 154  dlcl.travel() 155     print(dlcl.length()) 156     dlcl.add(3) 157     print(dlcl.is_empty()) 158  dlcl.travel() 159     dlcl.add(4) 160     dlcl.add(5) 161     dlcl.append(6) 162     dlcl.insert(-10,1) 163  dlcl.travel() 164     print(dlcl.length()) 165     dlcl.remove(6) 166  dlcl.travel() 167 
168     print(dlcl.search(7) ) 169     dlcl.append(55) 170     dlcl.travel()

各種數據結構主要是思想,不同的人實現方式都不一定一樣,同一個人多次實現也不一定一樣。所以以上代碼僅供參考~

如果有更簡潔的方式,歡迎大家批評指正哦~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM