python實(shí)現(xiàn)雙向鏈表 -- 詳細(xì)思路分析

雙鏈表的每個(gè)節(jié)點(diǎn)都有兩個(gè)指針莫鸭,一個(gè)指向直接后繼,一個(gè)指向直接前驅(qū)横殴。在雙向鏈表的任意一個(gè)節(jié)點(diǎn)都能很方便的訪問(wèn)其前后節(jié)點(diǎn)被因。其基本結(jié)構(gòu)如下:

雙向鏈表結(jié)構(gòu)圖

1.構(gòu)造雙向循環(huán)鏈表

雙向鏈表和單向鏈表只有在insert、append衫仑、remove氏身、add方法上有差別,因此這里可以使用面向?qū)ο蟮乃枷?/strong>惑畴,繼承于單向鏈表,然后重寫這四種方法航徙。

1.1 構(gòu)造節(jié)點(diǎn)

雙向鏈表的節(jié)點(diǎn)比單向鏈表多一個(gè)prev指針指向前一個(gè)節(jié)點(diǎn)

# 定義節(jié)點(diǎn)
class Node(object):
    """節(jié)點(diǎn)"""
    def __init__(self,item):
        self.elem = item
        self.next = None
        self.prev = None

1.2 重寫add函數(shù)【頭插法】

作用:在鏈表頭部添加元素

  • 傳入的item不是節(jié)點(diǎn)類型如贷,因此需要使用Node將其轉(zhuǎn)為節(jié)點(diǎn)。實(shí)例為node對(duì)象
  • 讓node指向下一個(gè)元素的指針指向當(dāng)前的頭節(jié)點(diǎn)到踏,即self.__head杠袱。node.next = self.__head
  • 將self.__head賦值為node。self.__head = node
  • 讓node的下一個(gè)節(jié)點(diǎn)的prev指針指向node【與單向鏈表的區(qū)別】
    【注意】
  • 必須先讓node的下一個(gè)指針先指向當(dāng)前的頭節(jié)點(diǎn)窝稿,然后重新設(shè)置node為頭節(jié)點(diǎn)
add函數(shù)圖解
def add(self,item):
        """頭部添加"""
        node = Node(item)
        node.next = self.__head
        self.__head = node
        node.next.prev = node # 讓node的下一個(gè)節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn)指向node


1.3 重寫insert函數(shù)

作用:在指定位置插入元素

  • 創(chuàng)建一個(gè)cur游標(biāo),起使指向頭節(jié)點(diǎn)的位置楣富,即cur = self.__head
  • 創(chuàng)建一個(gè)計(jì)數(shù)器count,用于記錄索引后和pos比較
  • 當(dāng)count移動(dòng)到pos位置【區(qū)別于單向鏈表移動(dòng)到pos-1位置伴榔,因?yàn)榇嬖谇昂笾羔樜坪钥梢砸苿?dòng)到pos位置】
  • 找到pos位置后庄萎,將node的next指針指向cur當(dāng)前節(jié)點(diǎn);將cur當(dāng)前節(jié)點(diǎn)的next指針指向node塘安,node的prev指針指向cur的prev節(jié)點(diǎn)【先操作node糠涛,不改變?cè)湵斫Y(jié)構(gòu)】
  • 讓node的prev指針指向當(dāng)前cur所在節(jié)點(diǎn)的prev節(jié)點(diǎn)
  • 讓cur所在節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn)的next指針指向node
  • 讓cur當(dāng)前節(jié)點(diǎn)的prev指針指向node
    【注意】
  • 當(dāng)輸入的pos<=0時(shí),視為其在頭部插入兼犯,直接調(diào)用add方法
  • 當(dāng)輸入的pos>鏈表的長(zhǎng)度時(shí)忍捡,視為在尾部,直接調(diào)用append方法
insert函數(shù)圖解
def insert(self,pos,item):
        """在指定位置插入"""
        if pos <=0:
            self.add(item)
        elif pos> (self.length() -1):
            self.append(item)
        else:
            cur = self.__head
            count = 0
            # 游標(biāo)直接走到pos的位置
            while count < pos :
                count += 1
                cur = cur.next
            # 當(dāng)循環(huán)推出后切黔,cur指向pos的位置
            node = Node(item)
            node.next = cur
            node.prev = cur.prev
            cur.prev.next = node
            cur.prev = node


1.4 重寫append函數(shù)【尾插法】

作用:在鏈表尾部添加元素

  • 創(chuàng)建一個(gè)cur游標(biāo)砸脊,起使指向頭節(jié)點(diǎn)的位置,即cur = self.__head
  • 當(dāng)cur.next為None時(shí)纬霞,則處于最后一個(gè)節(jié)點(diǎn)凌埂,因此遍歷條件為 while cur.next!=None
  • 讓cur游標(biāo)遍歷到鏈表最后一個(gè)節(jié)點(diǎn)的位置,讓當(dāng)前節(jié)點(diǎn)next指針指向node
  • 讓node的prev指針指向cur【與單向鏈表的區(qū)別】
    【注意】
  • 當(dāng)鏈表為空時(shí)险领,不存在cur.next侨舆,因此需要考慮鏈表為空的情況
  • 當(dāng)鏈表為空時(shí),直接將當(dāng)前的頭節(jié)點(diǎn)賦值為node


    append函數(shù)圖解
 def remove(self,item):
        """刪除節(jié)點(diǎn)"""
        cur = self.__head
        while cur != None:
            if cur.elem == item:
                # 先判斷此節(jié)點(diǎn)是否是頭節(jié)點(diǎn)
                self.__head = cur.next
                # cur.next可能是None
                if cur.next:
                    cur.next.prev = None
                else:
                    cur.prev.next = cur.next
                    # cur.next可能是None
                    if cur.next:
                        cur.next.prev = cur.prev
                break
            else:
                cur = cur.next


1.5 重寫remove函數(shù)

作用:刪除指定位置元素

  • 遍歷鏈表【while cur != None】,如果當(dāng)前節(jié)點(diǎn)不是要?jiǎng)h除的節(jié)點(diǎn)绢陌,則移動(dòng)cur
  • 當(dāng)cur指向的元素等于要?jiǎng)h除的元素相等時(shí)挨下,先判斷是否是頭節(jié)點(diǎn),如果是頭節(jié)點(diǎn)脐湾,直接讓self.__head = cur.next臭笆,讓cur.next.prev指向None【由于cur.next不一定存在,因此需要添加判斷條件if】
  • 如果不為頭節(jié)點(diǎn)秤掌,則讓cur的前一個(gè)結(jié)點(diǎn)的next指針指向cur的下一個(gè)節(jié)點(diǎn)cur.prev.next = cur.next愁铺;讓cur的下一個(gè)節(jié)點(diǎn)的prev指針指向cur的前一個(gè)節(jié)點(diǎn) cur.next.prev = cur.prev【由于cur.next不一定存在,因此需要添加判斷條件if】
    【注意】
  • 如果要?jiǎng)h除的節(jié)點(diǎn)為頭節(jié)點(diǎn)闻鉴,即cur處于head的位置茵乱,則直接讓頭節(jié)點(diǎn)指向cur的下一個(gè)節(jié)點(diǎn)即可
remove函數(shù)圖解
def remove(self,item):
        """刪除節(jié)點(diǎn)"""
        cur = self.__head
        while cur != None:
            if cur.elem == item:
                # 先判斷此節(jié)點(diǎn)是否是頭節(jié)點(diǎn)
                self.__head = cur.next
                # cur.next可能是None
                if cur.next:
                    cur.next.prev = None
                else:
                    cur.prev.next = cur.next
                    # cur.next可能是None
                    if cur.next:
                        cur.next.prev = cur.prev
                break
            else:
                cur = cur.next

2.完整代碼

# 雙向鏈表可以先繼承單向鏈表,然后重寫add孟岛、travel瓶竭、append、remove方法
class DoubleLinkList(SingleLinklist):
    def add(self,item):
        """頭部添加"""
        node = Node(item)
        node.next = self.__head
        self.__head = node
        node.next.prev = node # 讓node的下一個(gè)節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn)指向node

    def append(self,item):
        """尾部添加元素渠羞,只比單鏈表的append方法多一行代碼"""
        node = Node(item)
        if self.is_empty():
            self.__head = node
        else:
            cur = self.__head()
            while cur.next != None:
                cur = cur.next
            cur.next = node
            node.prev = cur

    def insert(self,pos,item):
        """在指定位置插入"""
        if pos <=0:
            self.add(item)
        elif pos> (self.length() -1):
            self.append(item)
        else:
            cur = self.__head
            count = 0
            # 游標(biāo)直接走到pos的位置
            while count < pos :
                count += 1
                cur = cur.next
            # 當(dāng)循環(huán)推出后斤贰,cur指向pos的位置
            node = Node(item)
            node.next = cur
            node.prev = cur.prev
            cur.prev.next = node
            cur.prev = node

    def remove(self,item):
        """刪除節(jié)點(diǎn)"""
        cur = self.__head
        while cur != None:
            if cur.elem == item:
                # 先判斷此節(jié)點(diǎn)是否是頭節(jié)點(diǎn)
                self.__head = cur.next
                # cur.next可能是None
                if cur.next:
                    cur.next.prev = None
                else:
                    cur.prev.next = cur.next
                    # cur.next可能是None
                    if cur.next:
                        cur.next.prev = cur.prev
                break
            else:
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市次询,隨后出現(xiàn)的幾起案子荧恍,更是在濱河造成了極大的恐慌,老刑警劉巖屯吊,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件送巡,死亡現(xiàn)場(chǎng)離奇詭異摹菠,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)授艰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門辨嗽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人淮腾,你說(shuō)我怎么就攤上這事糟需。” “怎么了谷朝?”我有些...
    開封第一講書人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵洲押,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我圆凰,道長(zhǎng)杈帐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任专钉,我火速辦了婚禮挑童,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘跃须。我一直安慰自己站叼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開白布菇民。 她就那樣靜靜地躺著尽楔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪第练。 梳的紋絲不亂的頭發(fā)上阔馋,一...
    開封第一講書人閱讀 51,578評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音娇掏,去河邊找鬼呕寝。 笑死,一個(gè)胖子當(dāng)著我的面吹牛婴梧,可吹牛的內(nèi)容都是我干的壁涎。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼志秃,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了嚼酝?” 一聲冷哼從身側(cè)響起浮还,我...
    開封第一講書人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎闽巩,沒(méi)想到半個(gè)月后钧舌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體担汤,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年洼冻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了崭歧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡撞牢,死狀恐怖率碾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情屋彪,我是刑警寧澤所宰,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站畜挥,受9級(jí)特大地震影響仔粥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蟹但,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一躯泰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧华糖,春花似錦麦向、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至十办,卻和暖如春秀撇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背向族。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工呵燕, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人件相。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓再扭,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親夜矗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子泛范,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355