Python雙向循環(huán)鏈表實(shí)現(xiàn)方法分析
本文實(shí)例講述了Python雙向循環(huán)鏈表實(shí)現(xiàn)方法。分享給大家供大家參考,具體如下:
最近身邊的朋友在研究用python來(lái)實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)。遇到一個(gè)問(wèn)題就是雙向循環(huán)鏈表的實(shí)現(xiàn),改指向的時(shí)候總是發(fā)蒙。
我自己嘗實(shí)現(xiàn)了一個(gè)python的雙向循環(huán)鏈表。附上代碼,希望對(duì)大家有幫助。
如果不懂什么是雙向循環(huán)鏈表的伙伴,需要補(bǔ)習(xí)一下數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ)之后哦~~~
在python當(dāng)中 用一個(gè)類(lèi)Node 來(lái)實(shí)現(xiàn)鏈表的節(jié)點(diǎn),節(jié)點(diǎn)數(shù)據(jù)有三個(gè)變量:
- prev:前驅(qū)指針: 用于指向當(dāng)前節(jié)點(diǎn)前一個(gè)節(jié)點(diǎn)
- next: 后繼指針 用于指向當(dāng)前節(jié)點(diǎn)后一個(gè)節(jié)點(diǎn)
- item: 值, 用于存儲(chǔ)該節(jié)點(diǎn)要存的數(shù)值
當(dāng)前節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn)我們叫他前驅(qū),后一個(gè)節(jié)點(diǎn)我們叫他后繼。
在鏈表類(lèi)當(dāng)中,我們有一個(gè)變量head是鏈表的頭指針
我們拿著鏈表的頭head,就可以對(duì)他進(jìn)行一些列操作:( 由于是雙向循環(huán)鏈表,修改指針特別容易出錯(cuò),我盡量說(shuō)的細(xì)致,方便大家參考)
判斷空:is_empty()
如果頭指針head沒(méi)有指向則鏈表是空的 否則不是空的
在頭部添加元素: add(item)
1 新建一個(gè)節(jié)點(diǎn) 里面的值是item。
2 放入頭部:
2.1 如果鏈表是空的,node的next和prev都指向自己,然后head再指向node
在尾部添加元素: append(item)
1 創(chuàng)建一個(gè)新節(jié)點(diǎn)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 新建一個(gè)節(jié)點(diǎn)node 里面的值是item
2 找到合適的位置插進(jìn)去:
2.1 如果pos <= 0 還小,那就執(zhí)行頭插方法 add()
2.2 如果pos >= 鏈表長(zhǎng)度, 那就執(zhí)行尾部插入 append()
2.3 如果pos位置在鏈表的中間:
2.3.1 定義一個(gè)臨時(shí)變量temp 按照傳入的pos找到要插入的位置的前一個(gè)元素
2.3.2 node的prev設(shè)為temp,node的next設(shè)為temp的next
2.3.3 temp的next指向的節(jié)點(diǎn)的prev改為node
2.3.4 temp的next改為node
得到鏈表長(zhǎng)度: length()
1 我們?cè)O(shè)置一個(gè)臨時(shí)變量temp初始設(shè)為head , 設(shè)置一個(gè)計(jì)數(shù)器count 初始為 0
2 令count自增1 然后temp改指向自己的下一個(gè)元素 一直到temp遇到None 為止,temp到了鏈表的最后一個(gè)元素
通過(guò)這樣的方式,統(tǒng)計(jì)出一共有多少個(gè)節(jié)點(diǎn)返回
遍歷鏈表數(shù)據(jù): travelji()
1 設(shè)置一個(gè)臨時(shí)變量temp初始化設(shè)為head
2 temp 每次輸出自己指向元素的值,然后在指向自己的下一個(gè)元素,一直temp為None 說(shuō)明到了列表的尾部
刪除鏈表元素: remove( item )
1 開(kāi)啟temp臨時(shí)變量 初始化為head ,
2 temp不斷指向自己的下一個(gè)元素,每次指向一個(gè)元素都檢查當(dāng)前值是不是item,如果找到item則刪除它返回True,如果沒(méi)找到就到尾部了就返回False
2.1 刪除過(guò)程:
2.1.1 temp的前一個(gè)元素的next改為temp的后一個(gè)元素
2.1.2 temp的后一個(gè)元素的prev改為前一個(gè)元素
查詢(xún)是否有元素:search()
設(shè)置一個(gè)臨時(shí)變量temp從head開(kāi)始,不斷指向自己下一個(gè),每次都檢查一下自己的值如果和item相同返回True結(jié)束
如果temp變成None 則到尾部了都沒(méi)找到 返回False
上代碼!
# -*- coding:utf-8 -*-
#!python3
#鏈表的節(jié)點(diǎn)
class Node(object):
def __init__(self , item ):
self.item = item #節(jié)點(diǎn)數(shù)值
self.prev = None #用于指向前一個(gè)元素
self.next = None #用于指向后一個(gè)元素
#雙向循環(huán)鏈表
class DoubleCircleLinkList(object):
def __init__(self):
self.__head = None #初始化的時(shí)候頭節(jié)點(diǎn)設(shè)為空、
#判斷鏈表是否為空,head為None 的話(huà)則鏈表是空的
def is_empty(self):
return self.__head is None
#頭部添加元素的方法
def add(self,item):
node = Node(item) #新建一個(gè)節(jié)點(diǎn)node 里面的值是item
# 如果鏈表是空的,則node的next和prev都指向自己(因?yàn)槭请p向循環(huán)),head指向node
if self.is_empty():
self.__head = node
node.next = node
node.prev = node
# 否則鏈表不空
else:
node.next = self.__head #node的next設(shè)為現(xiàn)在的head
node.prev = self.__head.prev #node的prev 設(shè)為現(xiàn)在head的prev
self.__head.prev.next = node #現(xiàn)在head的前一個(gè)元素的next設(shè)為node
self.__head.prev = node #現(xiàn)在head的前驅(qū) 改為node
self.__head = node #更改頭部指針
#尾部添加元素方法
def append(self , item):
#如果當(dāng)前鏈表是空的 那就調(diào)用頭部插入方法
if self.is_empty():
self.add(item)
#否則鏈表不為空
else :
node = Node(item) #新建一個(gè)節(jié)點(diǎn)node
#因?yàn)槭请p向循環(huán)鏈表,所以head的prev其實(shí)就是鏈表的尾部
node.next = self.__head #node的下一個(gè)設(shè)為頭
node.prev = self.__head.prev #node的前驅(qū)設(shè)為現(xiàn)在頭部的前驅(qū)
self.__head.prev.next = node #頭部前驅(qū)的后繼設(shè)為node
self.__head.prev = node #頭部自己的前驅(qū)改為node
#獲得鏈表長(zhǎng)度 節(jié)點(diǎn)個(gè)數(shù)
def length(self):
#如果鏈表是空的 就返回0
if self.is_empty():
return 0
#如果不是空的
else:
cur = self.__head #臨時(shí)變量cur表示當(dāng)前位置 初始化設(shè)為頭head
count = 1 #設(shè)一個(gè)計(jì)數(shù)器count,cur每指向一個(gè)節(jié)點(diǎn),count就自增1 目前cur指向頭,所以count初始化為1
#如果cur.next不是head,說(shuō)明cur目前不是最后一個(gè)元素,那么count就1,再讓cur后移一位
while cur.next is not self.__head:
count += 1
cur = cur.next
#跳出循環(huán)說(shuō)明所有元素都被累加了一次 返回count就是一共有多少個(gè)元素
return count
#遍歷鏈表的功能
def travel(self):
#如果當(dāng)前自己是空的,那就不遍歷
if self.is_empty():
return
#鏈表不空
else :
cur = self.__head #臨時(shí)變量cur表示當(dāng)前位置,初始化為鏈表的頭部
#只要cur的后繼不是頭說(shuō)明cur不是最后一個(gè)節(jié)點(diǎn),我們就輸出當(dāng)前值,并讓cur后移一個(gè)節(jié)點(diǎn)
while cur.next is not self.__head:
print( cur.item,end=" " )
cur = cur.next
#當(dāng)cur的后繼是head的時(shí)候跳出循環(huán)了,最后一個(gè)節(jié)點(diǎn)還沒(méi)有打印值 在這里打印出來(lái)
print( cur.item )
#置頂位置插入節(jié)點(diǎn)
def insert(self, pos , item ):
#如果位置<=0 則調(diào)用頭部插入方法
if pos <= 0:
self.add(item)
#如果位置是最后一個(gè)或者更大 就調(diào)用尾部插入方法
elif pos > self.length() - 1 :
self.append(item)
#否則插入位置就是鏈表中間
else :
index = 0 #設(shè)置計(jì)數(shù)器,用于標(biāo)記我們后移了多少步
cur = self.__head #cur標(biāo)記當(dāng)前所在位置
#讓index每次自增1 ,cur后移,當(dāng)index=pos-1的時(shí)候說(shuō)明cur在要插入位置的前一個(gè)元素,這時(shí)候停下
while index < pos - 1 :
index += 1
cur = cur.next
#跳出循環(huán),cur在要插入位置的前一個(gè)元素,將node插入到cur的后面
node = Node(item) #新建一個(gè)節(jié)點(diǎn)
node.next = cur.next #node的后繼設(shè)為cur的后繼
node.prev = cur #node的前驅(qū)設(shè)為cur
cur.next.prev = node #cur后繼的前驅(qū)改為node
cur.next = node #cur后繼改為node
#刪除節(jié)點(diǎn)操作
def remove(self,item):
#如果鏈表為空 直接不操作
if self.is_empty():
return
#鏈表不為空
else:
cur = self.__head #臨時(shí)變量標(biāo)記位置,從頭開(kāi)始
#如果頭結(jié)點(diǎn)就是 要?jiǎng)h除的元素
if cur.item == item:
#如果只有一個(gè)節(jié)點(diǎn) 鏈表就空了 head設(shè)為None
if self.length() == 1:
self.__head = None
#如果多個(gè)元素
else:
self.__head = cur.next #頭指針指向cur的下一個(gè)
cur.next.prev= cur.prev #cur后繼的前驅(qū)改為cur的前驅(qū)
cur.prev.next = cur.next #cur前驅(qū)的后繼改為cur的后繼
#否則 頭節(jié)點(diǎn)不是要?jiǎng)h除的節(jié)點(diǎn) 我們要向下遍歷
else:
cur = cur.next #把cur后移一個(gè)節(jié)點(diǎn)
#循環(huán)讓cur后移一直到鏈表尾元素位置,期間如果找得到就刪除節(jié)點(diǎn),找不到就跳出循環(huán),
while cur is not self.__head:
#找到了元素cur就是要?jiǎng)h除的
if cur.item == item:
cur.prev.next = cur.next #cur的前驅(qū)的后繼改為cur的后繼
cur.next.prev = cur.prev #cur的后繼的前驅(qū)改為cur的前驅(qū)
cur = cur.next
#搜索節(jié)點(diǎn)是否存在
def search(self , item):
#如果鏈表是空的一定不存在
if self.is_empty():
return False
#否則鏈表不空
else:
cur = self.__head #設(shè)置臨時(shí)cur從頭開(kāi)始
# cur不斷后移,一直到尾節(jié)點(diǎn)為止
while cur.next is not self.__head:
#如果期間找到了就返回一個(gè)True 結(jié)束運(yùn)行
if cur.item == item:
return True
cur = cur.next
# 從循環(huán)跳出來(lái)cur就指向了尾元素 看一下為元素是不是要找的 是就返回True
if cur.item ==item:
return True
#所有元素都不是 就返回False 沒(méi)找到
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()
運(yùn)行結(jié)果:
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ù)結(jié)構(gòu)主要是思想,不同的人實(shí)現(xiàn)方式都不一定一樣,同一個(gè)人多次實(shí)現(xiàn)也不一定一樣。所以以上代碼僅供參考~
如果有更簡(jiǎn)潔的方式,歡迎大家批評(píng)指正哦~
更多關(guān)于Python相關(guān)內(nèi)容感興趣的讀者可查看本站專(zhuān)題:《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python編碼操作技巧總結(jié)》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》及《Python入門(mén)與進(jìn)階經(jīng)典教程》
希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。
- python單向循環(huán)鏈表實(shí)例詳解
- Python數(shù)據(jù)結(jié)構(gòu)之循環(huán)鏈表詳解
- python實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)中雙向循環(huán)鏈表操作的示例
- python/golang實(shí)現(xiàn)循環(huán)鏈表的示例代碼
- python單向循環(huán)鏈表原理與實(shí)現(xiàn)方法示例
- Python實(shí)現(xiàn)的單向循環(huán)鏈表功能示例
- Python數(shù)據(jù)結(jié)構(gòu)與算法之鏈表定義與用法實(shí)例詳解【單鏈表、循環(huán)鏈表】
- python雙向鏈表實(shí)例詳解
- Python實(shí)現(xiàn)雙向鏈表基本操作
- python雙向循環(huán)鏈表實(shí)例詳解
相關(guān)文章
python pandas讀取csv后,獲取列標(biāo)簽的方法
今天小編就為大家分享一篇python pandas讀取csv后,獲取列標(biāo)簽的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-11-11
Python中的?Numpy?數(shù)組形狀改變及索引切片
這篇文章主要介紹了Python中的?Numpy?數(shù)組形狀改變及索引切片,Numpy提供了一個(gè)reshape()方法,它可以改變數(shù)組的形狀,返回一個(gè)新的數(shù)組,更多相關(guān)內(nèi)容需要的小伙伴可以參考下面文章2022-05-05
Python三數(shù)之和的實(shí)現(xiàn)方式
這篇文章主要介紹了Python三數(shù)之和的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05
Python 文件數(shù)據(jù)讀寫(xiě)的具體實(shí)現(xiàn)
這篇文章主要介紹了Python 文件數(shù)據(jù)讀寫(xiě)的具體實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01
Python實(shí)現(xiàn)Excel和CSV之間的相互轉(zhuǎn)換
通過(guò)使用Python編程語(yǔ)言,編寫(xiě)腳本來(lái)自動(dòng)化Excel和CSV之間的轉(zhuǎn)換過(guò)程,可以批量處理大量文件,定期更新數(shù)據(jù),并集成轉(zhuǎn)換過(guò)程到自動(dòng)化工作流程中,本文將介紹如何使用Python 實(shí)現(xiàn)Excel和CSV之間的相互轉(zhuǎn)換,需要的朋友可以參考下2024-03-03
Python新版極驗(yàn)驗(yàn)證碼識(shí)別驗(yàn)證碼教程詳解
這篇文章主要介紹了Python新版極驗(yàn)驗(yàn)證碼識(shí)別驗(yàn)證碼,極驗(yàn)驗(yàn)證是一種在計(jì)算機(jī)領(lǐng)域用于區(qū)分自然人和機(jī)器人的,通過(guò)簡(jiǎn)單集成的方式,為開(kāi)發(fā)者提供安全、便捷的云端驗(yàn)證服務(wù)2023-02-02
Python 普通最小二乘法(OLS)進(jìn)行多項(xiàng)式擬合的方法
今天小編就為大家分享一篇Python 普通最小二乘法(OLS)進(jìn)行多項(xiàng)式擬合的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-12-12
對(duì)python mayavi三維繪圖的實(shí)現(xiàn)詳解
今天小編就為大家分享一篇對(duì)python mayavi三維繪圖的實(shí)現(xiàn)詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-01-01

