Python雙向循環(huán)鏈表實現(xiàn)方法分析
本文實例講述了Python雙向循環(huán)鏈表實現(xiàn)方法。分享給大家供大家參考,具體如下:
最近身邊的朋友在研究用python來實現(xiàn)數(shù)據(jù)結構。遇到一個問題就是雙向循環(huán)鏈表的實現(xiàn),改指向的時候總是發(fā)蒙。
我自己嘗實現(xiàn)了一個python的雙向循環(huán)鏈表。附上代碼,希望對大家有幫助。
如果不懂什么是雙向循環(huán)鏈表的伙伴,需要補習一下數(shù)據(jù)結構的基礎之后哦~~~
在python當中 用一個類Node 來實現(xiàn)鏈表的節(jié)點,節(jié)點數(shù)據(jù)有三個變量:
- prev:前驅指針: 用于指向當前節(jié)點前一個節(jié)點
- next: 后繼指針 用于指向當前節(jié)點后一個節(jié)點
- item: 值, 用于存儲該節(jié)點要存的數(shù)值
當前節(jié)點的前一個節(jié)點我們叫他前驅,后一個節(jié)點我們叫他后繼。
在鏈表類當中,我們有一個變量head是鏈表的頭指針
我們拿著鏈表的頭head,就可以對他進行一些列操作:( 由于是雙向循環(huán)鏈表,修改指針特別容易出錯,我盡量說的細致,方便大家參考)
判斷空:is_empty()
如果頭指針head沒有指向則鏈表是空的 否則不是空的
在頭部添加元素: add(item)
1 新建一個節(jié)點 里面的值是item。
2 放入頭部:
2.1 如果鏈表是空的,node的next和prev都指向自己,然后head再指向node
在尾部添加元素: append(item)
1 創(chuàng)建一個新節(jié)點node 里面的值是item
2 放入尾部:
2.1 如果鏈表空,則執(zhí)行頭部添加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 新建一個節(jié)點node 里面的值是item
2 找到合適的位置插進去:
2.1 如果pos <= 0 還小,那就執(zhí)行頭插方法 add()
2.2 如果pos >= 鏈表長度, 那就執(zhí)行尾部插入 append()
2.3 如果pos位置在鏈表的中間:
2.3.1 定義一個臨時變量temp 按照傳入的pos找到要插入的位置的前一個元素
2.3.2 node的prev設為temp,node的next設為temp的next
2.3.3 temp的next指向的節(jié)點的prev改為node
2.3.4 temp的next改為node
得到鏈表長度: length()
1 我們設置一個臨時變量temp初始設為head , 設置一個計數(shù)器count 初始為 0
2 令count自增1 然后temp改指向自己的下一個元素 一直到temp遇到None 為止,temp到了鏈表的最后一個元素
通過這樣的方式,統(tǒng)計出一共有多少個節(jié)點返回
遍歷鏈表數(shù)據(jù): 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
上代碼!
# -*- coding:utf-8 -*- #!python3 #鏈表的節(jié)點 class Node(object): def __init__(self , item ): self.item = item #節(jié)點數(shù)值 self.prev = None #用于指向前一個元素 self.next = None #用于指向后一個元素 #雙向循環(huán)鏈表 class DoubleCircleLinkList(object): def __init__(self): self.__head = None #初始化的時候頭節(jié)點設為空、 #判斷鏈表是否為空,head為None 的話則鏈表是空的 def is_empty(self): return self.__head is None #頭部添加元素的方法 def add(self,item): node = Node(item) #新建一個節(jié)點node 里面的值是item # 如果鏈表是空的,則node的next和prev都指向自己(因為是雙向循環(huán)),head指向node if self.is_empty(): self.__head = node node.next = node node.prev = node # 否則鏈表不空 else: node.next = self.__head #node的next設為現(xiàn)在的head node.prev = self.__head.prev #node的prev 設為現(xiàn)在head的prev self.__head.prev.next = node #現(xiàn)在head的前一個元素的next設為node self.__head.prev = node #現(xiàn)在head的前驅 改為node self.__head = node #更改頭部指針 #尾部添加元素方法 def append(self , item): #如果當前鏈表是空的 那就調用頭部插入方法 if self.is_empty(): self.add(item) #否則鏈表不為空 else : node = Node(item) #新建一個節(jié)點node #因為是雙向循環(huán)鏈表,所以head的prev其實就是鏈表的尾部 node.next = self.__head #node的下一個設為頭 node.prev = self.__head.prev #node的前驅設為現(xiàn)在頭部的前驅 self.__head.prev.next = node #頭部前驅的后繼設為node self.__head.prev = node #頭部自己的前驅改為node #獲得鏈表長度 節(jié)點個數(shù) def length(self): #如果鏈表是空的 就返回0 if self.is_empty(): return 0 #如果不是空的 else: cur = self.__head #臨時變量cur表示當前位置 初始化設為頭head count = 1 #設一個計數(shù)器count,cur每指向一個節(jié)點,count就自增1 目前cur指向頭,所以count初始化為1 #如果cur.next不是head,說明cur目前不是最后一個元素,那么count就1,再讓cur后移一位 while cur.next is not self.__head: count += 1 cur = cur.next #跳出循環(huán)說明所有元素都被累加了一次 返回count就是一共有多少個元素 return count #遍歷鏈表的功能 def travel(self): #如果當前自己是空的,那就不遍歷 if self.is_empty(): return #鏈表不空 else : cur = self.__head #臨時變量cur表示當前位置,初始化為鏈表的頭部 #只要cur的后繼不是頭說明cur不是最后一個節(jié)點,我們就輸出當前值,并讓cur后移一個節(jié)點 while cur.next is not self.__head: print( cur.item,end=" " ) cur = cur.next #當cur的后繼是head的時候跳出循環(huán)了,最后一個節(jié)點還沒有打印值 在這里打印出來 print( cur.item ) #置頂位置插入節(jié)點 def insert(self, pos , item ): #如果位置<=0 則調用頭部插入方法 if pos <= 0: self.add(item) #如果位置是最后一個或者更大 就調用尾部插入方法 elif pos > self.length() - 1 : self.append(item) #否則插入位置就是鏈表中間 else : index = 0 #設置計數(shù)器,用于標記我們后移了多少步 cur = self.__head #cur標記當前所在位置 #讓index每次自增1 ,cur后移,當index=pos-1的時候說明cur在要插入位置的前一個元素,這時候停下 while index < pos - 1 : index += 1 cur = cur.next #跳出循環(huán),cur在要插入位置的前一個元素,將node插入到cur的后面 node = Node(item) #新建一個節(jié)點 node.next = cur.next #node的后繼設為cur的后繼 node.prev = cur #node的前驅設為cur cur.next.prev = node #cur后繼的前驅改為node cur.next = node #cur后繼改為node #刪除節(jié)點操作 def remove(self,item): #如果鏈表為空 直接不操作 if self.is_empty(): return #鏈表不為空 else: cur = self.__head #臨時變量標記位置,從頭開始 #如果頭結點就是 要刪除的元素 if cur.item == item: #如果只有一個節(jié)點 鏈表就空了 head設為None if self.length() == 1: self.__head = None #如果多個元素 else: self.__head = cur.next #頭指針指向cur的下一個 cur.next.prev= cur.prev #cur后繼的前驅改為cur的前驅 cur.prev.next = cur.next #cur前驅的后繼改為cur的后繼 #否則 頭節(jié)點不是要刪除的節(jié)點 我們要向下遍歷 else: cur = cur.next #把cur后移一個節(jié)點 #循環(huán)讓cur后移一直到鏈表尾元素位置,期間如果找得到就刪除節(jié)點,找不到就跳出循環(huán), while cur is not self.__head: #找到了元素cur就是要刪除的 if cur.item == item: cur.prev.next = cur.next #cur的前驅的后繼改為cur的后繼 cur.next.prev = cur.prev #cur的后繼的前驅改為cur的前驅 cur = cur.next #搜索節(jié)點是否存在 def search(self , item): #如果鏈表是空的一定不存在 if self.is_empty(): return False #否則鏈表不空 else: cur = self.__head #設置臨時cur從頭開始 # cur不斷后移,一直到尾節(jié)點為止 while cur.next is not self.__head: #如果期間找到了就返回一個True 結束運行 if cur.item == item: return True cur = cur.next # 從循環(huán)跳出來cur就指向了尾元素 看一下為元素是不是要找的 是就返回True if cur.item ==item: return True #所有元素都不是 就返回False 沒找到 return False if __name__ == "__main__": dlcl = DoubleCircleLinkList() print(dlcl.search(7)) dlcl.travel() dlcl.remove(1) print(dlcl.length()) print(dlcl.is_empty()) dlcl.append(55) print(dlcl.search(55)) dlcl.travel() dlcl.remove(55) dlcl.travel() print(dlcl.length()) dlcl.add(3) print(dlcl.is_empty()) dlcl.travel() dlcl.add(4) dlcl.add(5) dlcl.append(6) dlcl.insert(-10,1) dlcl.travel() print(dlcl.length()) dlcl.remove(6) dlcl.travel() print(dlcl.search(7) ) dlcl.append(55) dlcl.travel()
運行結果:
False
0
True
True
55
0
False
3
1 5 4 3 6
5
1 5 4 3
False
1 5 4 3 55
各種數(shù)據(jù)結構主要是思想,不同的人實現(xiàn)方式都不一定一樣,同一個人多次實現(xiàn)也不一定一樣。所以以上代碼僅供參考~
如果有更簡潔的方式,歡迎大家批評指正哦~
更多關于Python相關內(nèi)容感興趣的讀者可查看本站專題:《Python數(shù)據(jù)結構與算法教程》、《Python編碼操作技巧總結》、《Python函數(shù)使用技巧總結》、《Python字符串操作技巧匯總》及《Python入門與進階經(jīng)典教程》
希望本文所述對大家Python程序設計有所幫助。
- python單向循環(huán)鏈表實例詳解
- Python數(shù)據(jù)結構之循環(huán)鏈表詳解
- python實現(xiàn)數(shù)據(jù)結構中雙向循環(huán)鏈表操作的示例
- python/golang實現(xiàn)循環(huán)鏈表的示例代碼
- python單向循環(huán)鏈表原理與實現(xiàn)方法示例
- Python實現(xiàn)的單向循環(huán)鏈表功能示例
- Python數(shù)據(jù)結構與算法之鏈表定義與用法實例詳解【單鏈表、循環(huán)鏈表】
- python雙向鏈表實例詳解
- Python實現(xiàn)雙向鏈表基本操作
- python雙向循環(huán)鏈表實例詳解
相關文章
Python OpenCV 基于圖像邊緣提取的輪廓發(fā)現(xiàn)函數(shù)
這篇文章主要介紹了Python OpenCV 基于圖像邊緣提取的輪廓發(fā)現(xiàn)函數(shù),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-03-03如何解決pytorch訓練過程中CPU內(nèi)存溢出問題
這篇文章主要介紹了如何解決pytorch訓練過程中CPU內(nèi)存溢出問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09使用python tkinter實現(xiàn)各種個樣的撩妹鼠標拖尾效果
這篇文章主要介紹了使用python tkinter實現(xiàn)各種個樣的撩妹鼠標拖尾效果,本文通過實例代碼,給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-09-09Python+Matplotlib繪制發(fā)散條形圖的示例代碼
發(fā)散條形圖(Diverging Bar)是一種用于顯示數(shù)據(jù)分布的圖表,可以幫助我們比較不同類別或分組的數(shù)據(jù)的差異和相對性,本文介紹了Matplotlib繪制發(fā)散條形圖的函數(shù)源碼,需要的可以參考一下2023-06-06python實現(xiàn)web應用框架之增加動態(tài)路由
這篇文章主要介紹web應用框架如何添加動態(tài)路由,在我們編寫的框架中,我們添加動態(tài)路由,是使用了正則表達式,同時在注冊的時候,需要注明該路由是請求路由,文中有詳細的代碼示例,需要的朋友可以參考下2023-05-05