Python實現(xiàn)鏈表

用Python玩轉數(shù)據(jù)結構

鏈表

節(jié)點類

根據(jù)在前學過的數(shù)據(jù)結構看成,那么必須有節(jié)點缠借,Python里面沒有指針的說法柿估,所以我們用引用來實現(xiàn)

節(jié)點類的方法

節(jié)點類最基本的功能包括:更新數(shù)據(jù)歧譬,查詢數(shù)據(jù)岸浑,更新后繼節(jié)點和查詢后繼節(jié)點。

class Node(object):
    def __init__(self, data):
        self.data = data
        self.next_node = None

    def get_data(self):
        """
        獲取當前節(jié)點的數(shù)據(jù)
        :return: 返回當前節(jié)點的數(shù)據(jù)
        """
        return self.data

    def set_data(self, data):
        """
        設置節(jié)點的數(shù)據(jù)為傳入的數(shù)據(jù)
        :param data:
        :return: 無返回
        """
        self.data = data

    def get_next(self):
        """
        獲取當前節(jié)帶點的指向
        :return: 返回指向的對象
        """
        return self.next

    def set_next(self, next_node):
        """
        修改節(jié)點的指向
        :param next_node:
        :return:無返回
        """
        self.next_node = next_node

鏈表類

我們把節(jié)點類先實現(xiàn)瑰步,然后再來實現(xiàn)鏈表類矢洲。我們定義一個鏈表類,并實現(xiàn)初始化方法缩焦。在初始化方法中定義了兩個屬性读虏,分別是headlength屬性。head屬性表明頭節(jié)點袁滥,在初始化的時候指向None盖桥。length屬性表明鏈表的長度,方便判斷列表是否為空和返回鏈表的長度题翻。

class Linked_list(object):
    def __init__(self):
        """
        初始化方法揩徊,定義一個長度屬性方便統(tǒng)計和判斷
        """
        self.head = None
        self.length = 0

鏈表類的方法

然后我們一個想想我們的鏈表類需要哪些方法,這是有鏈表的特性覺得的不是嗎嵌赠?大概列一個列表吧:

  • 在末尾插入數(shù)據(jù)
  • 在開頭插入數(shù)據(jù)
  • 在指定位置插入 數(shù)據(jù)
  • 修改指定位置的數(shù)據(jù)
  • 獲取指定位置的數(shù)據(jù)
  • 查找數(shù)據(jù)在鏈表中的數(shù)據(jù)
  • 刪除指定位置的數(shù)據(jù)
  • 展示整個鏈表
  • 刪除整個鏈表
  • 判斷這個鏈表是否為空

大概就是這些看起來是不是有點多塑荒,但是不用擔心,我們一點一點的來實現(xiàn)姜挺。

判斷鏈表是否為空

首先是判斷一個鏈表是否為空齿税,這個很好實現(xiàn),我們先看代碼:

    def isEmpty(self):
        """
        判斷鏈表是否為空初家,如果為空返回True偎窘,否則為False
        :return:
        """
        return self.length == 0

除去注釋也就一行代碼的事情,用鏈表的長度和0做一個比較溜在,不相等返回False相等返回True然后就能很好的判斷了陌知。

獲取鏈表的長度

同樣的獲取鏈表的長度也很簡單:

    def get_length(self):
        return self.length
在鏈表末尾插入數(shù)據(jù)

然后就是在末尾插入數(shù)據(jù)

    def append(self, data_or_node):
        """
        在鏈表的末尾增加一個節(jié)點
        :param data_or_node:
        :return:
        """
        item = None
        # 這一個判斷是為了判斷傳進來的數(shù)據(jù)是什么類型的
        if isinstance(data_or_node, Node):
            item = data_or_node
        else:
            item = Node(data_or_node)

        if not self.head:
            self.head = item
            self.length += 1
        else:
            node = self.head
            while node.next_node:
                node = node.next_node
            node.next_node = item
            self.length += 1

首先是判斷傳入進來的數(shù)據(jù)是什么類型,如果已經是一個節(jié)點類的話我們就不用轉換掖肋,如果不是仆葡,我們就將其轉換為節(jié)點類。這里用到了isinstance()方法,這個方法的作用是判一個對象是否是一個已知的類型沿盅,考慮繼承的情況把篓。然后判斷這個鏈表的頭結點是否存在,也可以通過判斷鏈表的長度來實現(xiàn)腰涧。如果頭節(jié)點不存在韧掩,就將這個節(jié)點變?yōu)轭^節(jié)點。所以有了這個引用窖铡,將item的值賦值給head疗锐。如果不是的話我們首先就要找到尾節(jié)點,通過頭節(jié)點開始循環(huán)费彼,一直找到尾節(jié)點滑臊,然后引用。不管是那種情況都不能忘記將鏈表的長度加上1

在鏈表的頭部插入數(shù)據(jù)

頭部插入數(shù)據(jù)也很簡單箍铲,

    def add(self, data_or_node):
        """
        在鏈表的最前方插入一個數(shù)據(jù)
        :param data_or_node:
        :return:
        """
        if isinstance(data_or_node, Node):
            item = data_or_node
        else:
            item = Node(data_or_node)

        if not self.head:
            self.head = item
            self.length += 1
        else:
            next_node = self.head
            self.head = item
            item.next_node = next_node
            self.length += 1

大部分都差不多雇卷,只是在判斷不是空鏈表之后的處理有點不一樣。我們將之前頭節(jié)點的值賦值給一個變量颠猴,然后將我們傳入的變量指向給原頭節(jié)點关划,同時將頭節(jié)點指向我們傳入的變量。

在指定位置插入節(jié)點

我們可以通過指定位置插入節(jié)點這個是很必要的一個方法芙粱,先看代碼:

    def insert(self, index, data_or_node):
        """
        根據(jù)給定的索引在鏈表中插入一個節(jié)點
        :param index: 索引
        :param data_or_node: 數(shù)據(jù)
        :return: 無返回
        """
        if self.isEmpty():
            print("this Linked list is Empty")
            return

        if index < 0 or index >= self.length:
            print("error: out of index ")
            return
        item = None
        if isinstance(data_or_node, Node):
            item = data_or_node
        else:
            item = Node(data_or_node)

        if index == 0:
            self.add(item)
            return

        j = 0
        node = self.head
        prev = self.head
        while j < index:
            prev = node
            node = node.next_node
            j += 1
        prev.next_node = item
        item.next_node = node
        self.length += 1

對于所有給出索引的方法來說祭玉,我們都需要判斷這個鏈表是否為空和給定的索引是否越界。然后再把傳入的節(jié)點通過判斷轉換為節(jié)點類春畔。如果索引的值是0的話就是在頭部插入脱货,我們直接調用在前面定義的內部方法就好,然后記得return結束函數(shù)律姨,不然那你會將你的所有的節(jié)點的值都改變振峻。然后就是關鍵的步驟,我們定義三個變量择份,作用分別是:計數(shù)器扣孟、記錄前置節(jié)點和記錄當前節(jié)點。最開始的節(jié)點都為頭節(jié)點荣赶,然后開始循環(huán)凤价,當j小于索引值的時候呢,循環(huán)拔创,同時將node的值賦值給prev佛吓,將節(jié)點記錄下來鼻吮。當找到插入節(jié)點的位置的時候眷蚓,我們將prev指向我們傳入的節(jié)點阀圾,然后將傳入的節(jié)點再指向給item就完成在指定位置插入。只要是涉及到節(jié)點個數(shù)的變化的操作的時候一定要記得對length進行對應的操作。

刪除指定位置的節(jié)點

說完了增加侣滩,按照慣例就是刪除了口注。首先是刪除指定位置的節(jié)點:

    def delete(self, index):
        """
        根據(jù)給定的索引刪除一個節(jié)點
        :param index: 索引
        :return: 無返回
        """
        if self.isEmpty():
            print("this Linked list is Empty")
            return

        if index < 0 or index >= self.length:
            print("error: out of index ")
            return

        if index == 0:
            self.head = self.head.next_node
            self.length -= 1

        j = 0
        node = self.head
        prev = self.head
        while j < index:
            prev = node
            node = node.next_node
            j += 1
        prev.next_node = node.next_node
        self.length -= 1

首先還是幾個判斷,然后如果是刪除頭節(jié)點君珠,我們將頭節(jié)點的值指向頭節(jié)點的下一個寝志。如果不是,就和插入很像了策添,找到索引對應的位置澈段,然后將prev直接指向node的下一個,然后鏈表長度減1舰攒。

刪除整個鏈表

刪除了一個節(jié)點就像刪除整個鏈表,這個代碼也超級簡單:

    def clear(self):
        """
        清除鏈表
        :return: 無返回
        """
        self.head = None
        self.length = 0

我們只需要將鏈表的頭節(jié)點再指向為空悔醋,然后長度變?yōu)?就好摩窃。

修改指定位置的節(jié)點的值

刪除也很簡單,下面來說修改芬骄,修改指定位置節(jié)點的值

    def updata_node_item(self, index, data):
        """
        根據(jù)給出的索引更新一個節(jié)點的值
        :param index: 索引
        :param data: 更新的值
        :return: 無返回
        """
        if self.isEmpty():
            print("this Linked list is Empty")
            return

        if index < 0 or index >= self.length:
            print("error: out of index ")
            return

        j = 0
        node = self.head
        while j < index:
            node = node.next_node
            j += 1
        node.data = data

就只是常規(guī)的判斷然后是循環(huán)找到節(jié)點后修改值就好猾愿。

根據(jù)索引獲得對應節(jié)點的值

查找是一個很重要的功能,有兩種需要我們實現(xiàn)账阻,先來第一種:根據(jù)索引查找對應的值:

 def get_node_item(self, index):
        """
        根據(jù)索引獲取獲取節(jié)點的值
        :param index: 索引
        :return: 返回索引對應節(jié)點的值
        """
        if self.isEmpty():
            print("this Linked list is Empty")
            return

        if index < 0 or index >= self.length:
            print("error: out of index ")
            return

        j = 0
        node = self.head
        while j < index:
            node = node.next_node
            j += 1
        return node.data

和修改很類似蒂秘,不同的是我們直接返回值就好

根據(jù)值查對應的節(jié)點的索引

我們也可以傳一個值然后找對應的索引,這樣就能做到:

    def get_node_index(self, data):
        """
        查找一個數(shù)據(jù)的索引
        :param data:數(shù)據(jù)
        :return:索引
        """
        node = self.head
        j = 0
        while node.next_node:
            if node.data == data:
                return j
            else:
                node = node.next_node
            j += 1
        if j == self.length:
            print("%s is not found " % str(data))

其實都差不多淘太,但是呢有一種情況需要注意姻僧,就是如果當j的值都等于鏈表的長度的時候說明,鏈表當中沒有這個值蒲牧。

展示鏈表

其實到這里就差不多了撇贺,然后就是一個展示整個鏈表的方法:

    def show(self):
        """
        展示鏈表
        :return:
        """
        if self.isEmpty():
            print("this is a empty linked list")
        n = 0
        node = self.head
        while n < self.length:
            print("node %d : %s" % (n, node.data))
            node = node.next_node
            n += 1

試試效果

mylinked = Linked_list()
for i in range(10):
    mylinked.append(i)
mylinked.show()
print(mylinked.get_length())
print(mylinked.get_node_index(4))
print(mylinked.get_node_item(5))
print(mylinked.updata_node_item(4, 20))
print(mylinked.delete(8))
print(mylinked.insert(0, 420))
mylinked.show()

結果:

node 0 : 0
node 1 : 1
node 2 : 2
node 3 : 3
node 4 : 4
node 5 : 5
node 6 : 6
node 7 : 7
node 8 : 8
node 9 : 9
10
4
5
None
None
None
node 0 : 420
node 1 : 0
node 2 : 1
node 3 : 2
node 4 : 3
node 5 : 20
node 6 : 5
node 7 : 6
node 8 : 7
node 9 : 9

Process finished with exit code 0

完整代碼傳送門:點這里

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市冰抢,隨后出現(xiàn)的幾起案子松嘶,更是在濱河造成了極大的恐慌,老刑警劉巖挎扰,帶你破解...
    沈念sama閱讀 221,331評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翠订,死亡現(xiàn)場離奇詭異,居然都是意外死亡遵倦,警方通過查閱死者的電腦和手機尽超,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來骇吭,“玉大人橙弱,你說我怎么就攤上這事。” “怎么了棘脐?”我有些...
    開封第一講書人閱讀 167,755評論 0 360
  • 文/不壞的土叔 我叫張陵斜筐,是天一觀的道長。 經常有香客問我蛀缝,道長顷链,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,528評論 1 296
  • 正文 為了忘掉前任屈梁,我火速辦了婚禮嗤练,結果婚禮上,老公的妹妹穿的比我還像新娘在讶。我一直安慰自己煞抬,他們只是感情好,可當我...
    茶點故事閱讀 68,526評論 6 397
  • 文/花漫 我一把揭開白布构哺。 她就那樣靜靜地躺著革答,像睡著了一般。 火紅的嫁衣襯著肌膚如雪曙强。 梳的紋絲不亂的頭發(fā)上残拐,一...
    開封第一講書人閱讀 52,166評論 1 308
  • 那天,我揣著相機與錄音碟嘴,去河邊找鬼溪食。 笑死,一個胖子當著我的面吹牛娜扇,可吹牛的內容都是我干的错沃。 我是一名探鬼主播,決...
    沈念sama閱讀 40,768評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼雀瓢,長吁一口氣:“原來是場噩夢啊……” “哼捎废!你這毒婦竟也來了?” 一聲冷哼從身側響起致燥,我...
    開封第一講書人閱讀 39,664評論 0 276
  • 序言:老撾萬榮一對情侶失蹤登疗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后嫌蚤,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辐益,經...
    沈念sama閱讀 46,205評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,290評論 3 340
  • 正文 我和宋清朗相戀三年脱吱,在試婚紗的時候發(fā)現(xiàn)自己被綠了智政。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,435評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡箱蝠,死狀恐怖续捂,靈堂內的尸體忽然破棺而出垦垂,到底是詐尸還是另有隱情,我是刑警寧澤牙瓢,帶...
    沈念sama閱讀 36,126評論 5 349
  • 正文 年R本政府宣布劫拗,位于F島的核電站,受9級特大地震影響矾克,放射性物質發(fā)生泄漏页慷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,804評論 3 333
  • 文/蒙蒙 一胁附、第九天 我趴在偏房一處隱蔽的房頂上張望酒繁。 院中可真熱鬧,春花似錦控妻、人聲如沸州袒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,276評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽稳析。三九已至,卻和暖如春弓叛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背诚纸。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工撰筷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人畦徘。 一個月前我還...
    沈念sama閱讀 48,818評論 3 376
  • 正文 我出身青樓毕籽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親井辆。 傳聞我的和親對象是個殘疾皇子关筒,可洞房花燭夜當晚...
    茶點故事閱讀 45,442評論 2 359

推薦閱讀更多精彩內容

  • 搞懂單鏈表常見面試題 Hello 繼上次的 搞懂基本排序算法,這個一星期杯缺,我總結了蒸播,我所學習和思考的單鏈表基礎知識...
    醒著的碼者閱讀 4,591評論 1 45
  • ORA-00001: 違反唯一約束條件 (.) 錯誤說明:當在唯一索引所對應的列上鍵入重復值時,會觸發(fā)此異常萍肆。 O...
    我想起個好名字閱讀 5,333評論 0 9
  • 一袍榆、概念梳理 鏈表是計算機科學里面應用應用最廣泛的數(shù)據(jù)結構之一。它是最簡單的數(shù)據(jù)結構之一塘揣,同時也是比較高階的數(shù)據(jù)結...
    黑加侖妞閱讀 4,079評論 0 0
  • 摘自《維基百科》?鏈表(Linked list)是一種常見的基礎數(shù)據(jù)結構包雀,是一種線性表,但是并不會按線性的順序存儲...
    ChinaChong閱讀 1,703評論 0 52
  • 一些概念 數(shù)據(jù)結構就是研究數(shù)據(jù)的邏輯結構和物理結構以及它們之間相互關系亲铡,并對這種結構定義相應的運算才写,而且確保經過這...
    Winterfell_Z閱讀 5,850評論 0 13