數(shù)據(jù)結(jié)構(gòu)-雙向鏈表(Python實現(xiàn))

數(shù)據(jù)結(jié)構(gòu)在編程世界中一直是非常重要的一環(huán)盯串,不管是開發(fā)還是算法抚垄,哪怕是單純?yōu)榱嗣嬖嚕瑪?shù)據(jù)結(jié)構(gòu)都是必修課氮采,今天我們介紹鏈表中的一種——雙向鏈表的代碼實現(xiàn)殷绍。

好了,話不多說直接上代碼鹊漠。

雙向鏈表

首先主到,我們定義一個節(jié)點類:Node

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None
        self.prev = None
    def getData(self):
        return self.data

    def setData(self, data):
        self.data = data

    def getNext(self):
        return self.next

    def getPrev(self):
        return self.prev

好,我們定義了節(jié)點類躯概,并實現(xiàn)了獲取登钥、修改節(jié)點數(shù)據(jù)、獲取上一個/下一個節(jié)點的方法楞陷。

通過node = Node(10)就可以實例化一個節(jié)點啦怔鳖。

接下來我們來定義鏈表類:

class TwoWayList:
    def __init__(self):
        self.head = None
        self.tail = None
        self.length = 0

好茉唉,我們定義了一個鏈表類固蛾,并設(shè)置三個屬性结执,head表示頭節(jié)點,tail表示尾節(jié)點艾凯,length表示鏈表長度献幔,接下來,我們給鏈表類添加一些方法趾诗。

  • 判斷鏈表是否為空:
    def isEmpty(self):
        return self.head == None
  • 在鏈表尾部添加節(jié)點:
    def append(self, item):
        if self.length == 0:
            node = Node(item)
            self.head = node
            self.tail = node
            self.length = 1
            return
        node = Node(item)
        tail = self.tail
        tail.next = node
        node.prev = tail
        self.tail = node
        self.length += 1

添加節(jié)點的時候蜡感,我們首先要判斷鏈表是否為空,另外要注意給原本的尾節(jié)點設(shè)置next屬性恃泪,新的尾節(jié)點設(shè)置prev屬性郑兴,更新鏈表的tail和length屬性。

  • 鏈表中插入節(jié)點:
    def insert(self, index, item):
        length = self.length
        if (index<0 and abs(index)>length) or (index>0 and index>=length):
            return False
        if index < 0:
            index = index + length
        if index == 0:
            node = Node(item)
            if self.head != None:
                self.head.prev = node
            else:
                self.tail = node
            node.next = self.head
            self.head = node
            self.length += 1
            return True
        if index == length - 1:
            return self.append(item)


        node1 = self.head
        for i in range(0, index):
            node1 = node1.next
        node2 = node1.next

        node = Node(item)
        node.prex = node1
        node.next = node2
        node1.next = node
        node2.prev = node

        self.length += 1
        return True

插入節(jié)點時候贝乎,我們參數(shù)為下標index和數(shù)據(jù)item情连,我們默認在指定下標的后面插入新節(jié)點。

在這里我們同樣要特殊考慮頭節(jié)點和尾結(jié)點的情況览效。

在執(zhí)行插入時先將新節(jié)點的next却舀、prev屬性指向相應(yīng)節(jié)點,在將前后節(jié)點的next和prev指向新節(jié)點锤灿,同時注意更新鏈表的length屬性挽拔。

  • 根據(jù)節(jié)點數(shù)據(jù)獲取鏈表上的節(jié)點
    def get(self, data):
        node = self.head
        for i in range(self.length):
            if node.data == data:
                return node
            else:
                node = node.next
        else:
            return False
  • 根據(jù)下標獲取鏈表上的節(jié)點
    def getByIndex(self, index):
        if index >= self.length:
            return False
        if index == 0:
            return self.head

        now = self.head
        for i in range(self.length):
            if i == index:
                return now
            now = now.next
  • 更新指定下標節(jié)點的數(shù)據(jù)
    def setData(self, index, data):
        if index >= self.length:
            return False
        if index == 0:
            self.head.data = data

        now = self.head
        for i in range(self.length):
            if i == index:
                now.data = data
                return True
            now = now.next
  • 刪除指定下標的節(jié)點
    def remove(self, index):
        if index >= self.length:
            return False
        if index == 0:
            self.head = self.head.next
            if self.length != 1:
                self.head.prev = None
            self.length -= 1
            return True
        if index == self.length-1:
            self.tail = self.tail.prev
            self.tail.next = None
            self.length -= 1
            return True

        now = self.head
        for i in range(self.length):
            if i == index:
                now.next.prev = now.prev
                now.prev.next = now.next
                self.length -= 1
                return True
            now = now.next

注意要更新length屬性,如果刪除頭節(jié)點還要更新head屬性但校,如果刪除尾結(jié)點要更新tail屬性螃诅。

  • 鏈表翻轉(zhuǎn)
    def reverse(self):
        now = self.head
        last = None
        for i in range(self.length):
            last = now
            now = now.next
            tmp = last.prev
            last.prev = last.next
            last.next = tmp
        tmp = self.head
        self.head = self.tail
        self.tail = tmp
        return True

鏈表翻轉(zhuǎn)我們不光要更新tail和head屬性,還要將每一個節(jié)點上的next和prev屬性調(diào)換始腾。

  • 清空鏈表
    def clear(self):
        self.head = None
        self.tail = None
        self.length = 0
  • 實現(xiàn)鏈表類的str方法州刽,定義print()函數(shù)打印鏈表的方式
    def __str__(self):
        string = ''
        node = self.head
        for i in range(self.length):
            string += str(node.data) + '/'
            node = node.next
        return string

這里我們讓print()函數(shù)打印鏈表時,從頭節(jié)點開始依次打印每個節(jié)點的數(shù)據(jù)浪箭,并用/符號分割穗椅。

好啦,一個雙向鏈表我們就定義好了奶栖,并實現(xiàn)了一些操作鏈表的方法匹表,我們了來測試一下我們定義的鏈表吧~

li = TwoWayList()
li.isEmpty()
li.insert(0, 1)
li.getByIndex(0)
li.remove(0)

print(li)
li.append(1)

print(li)
li.append(2)
print(li)
li.append(4)
print(li)
li.insert(2,3)
print(li)
li.insert(3,4)

print(li)
li.remove(2)
print(li)
li.setData(2,10)
print(li)
li.reverse()
print(li)
print(li.get(2).data)
print(li.getByIndex(1).data)

執(zhí)行上面的操作,檢查一下你的輸出吧宣鄙,你還有什么關(guān)于鏈表的應(yīng)用留言告訴我把袍镀。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市冻晤,隨后出現(xiàn)的幾起案子苇羡,更是在濱河造成了極大的恐慌,老刑警劉巖鼻弧,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件设江,死亡現(xiàn)場離奇詭異锦茁,居然都是意外死亡,警方通過查閱死者的電腦和手機叉存,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門码俩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人歼捏,你說我怎么就攤上這事稿存。” “怎么了瞳秽?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵瓣履,是天一觀的道長。 經(jīng)常有香客問我练俐,道長拂苹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任痰洒,我火速辦了婚禮瓢棒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘丘喻。我一直安慰自己脯宿,他們只是感情好,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布泉粉。 她就那樣靜靜地躺著连霉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嗡靡。 梳的紋絲不亂的頭發(fā)上跺撼,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天,我揣著相機與錄音讨彼,去河邊找鬼歉井。 笑死,一個胖子當著我的面吹牛哈误,可吹牛的內(nèi)容都是我干的哩至。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼蜜自,長吁一口氣:“原來是場噩夢啊……” “哼菩貌!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起重荠,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤箭阶,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仇参,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡媳危,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了冈敛。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡鸣皂,死狀恐怖抓谴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情寞缝,我是刑警寧澤癌压,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站荆陆,受9級特大地震影響滩届,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜被啼,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一帜消、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧浓体,春花似錦泡挺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至生闲,卻和暖如春媳溺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背碍讯。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工悬蔽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人捉兴。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓屯阀,卻偏偏與公主長得像,于是被迫代替她去往敵國和親轴术。 傳聞我的和親對象是個殘疾皇子难衰,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容