日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

实现单链表--Python

發布時間:2025/4/5 python 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 实现单链表--Python 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

單鏈表的結構

單鏈表結點的組成:

  • 元素
  • 鏈接域(保存下一結點的地址)

    在單鏈表里,表里的n 個結點通過鏈接形成一條結點鏈。從表里的任一個結點都可以找到保存下一個元素的結點。
    鏈表中的一個重要部分就是頭指針。頭指針保存著鏈表首結點的標識,通過頭指針可以十分方便的對鏈表進行:訪問元素、遍歷、增刪改查等操作
  • TODO:補充單鏈表的特性

    實現

    定義節點類

    節點是鏈表的基本組成部分

    class Node : # 只定義初始化操作def __init__(self, elm, next_=None):self.elem = elem# 因為Python中next是一個內置的函數,為區分,故在變量名后添加"_"self.next_ = next_

    定義單鏈表類

    # 單鏈表類只有一個 _head 域,表示單鏈表的頭指針 class SingleList:def __init__(self):self._head = None

    變量前的單下劃線表示私有變量,不要在對象的外部去訪問。python語言沒有為定義私有變量提供專門的機制,只能通過約定和良好的編程習慣來保護對象的私有屬性。

    定義異常類

    為了能合理處理一些鏈表操作中遇到的錯誤狀態,如在執行方法時遇到了無法操作的錯誤參數,首先定義一個異常類LinkedListUnderflow,這里將它定義為標準異常類ValueError的子類,pass表示空語句,即什么都不做。

    TODO: 在這里直接拋出ValueError也沒問題,但定義了自己的異常類就可以寫專門的異常處理器。

    class LinkedListUnderflow(ValueError):pass

    對鏈表的具體操作

    刪除鏈表

    在Python中,如果一個對象未被引用,則該對象會被當做垃圾并進行回收。所以刪除鏈表只需將頭指針設為None,使得鏈表對象不被引用

    def del_list(self):self._head = None

    判斷表空

    在Python里檢查_head值是否為None,如果為None,則說明_head不指向任何對象

    def is_empty(self):return self._head is None

    判斷表滿

    因為鏈表沒有一個固定的容量,可以動態擴充,所以在內容充足的情況下,鏈表是不會滿的



    鏈表長度

    算法描述:

  • 創建計數器
  • 遍歷至最后一個節點
  • 代碼實現:

    def length(self):'''計算鏈表長度'''point = self._headcount = 1while point.next_ != None:point = point.next_count += 1return count

    思考1:為什么需要新建一個point變量


    遍歷鏈表

    算法描述:

  • 創建計數器
  • 遍歷至最后一個節點
  • 算法實現:

    def traverse(self):'''遍歷鏈表'''point = self._headindex = 0while point.next_ != None:index += 1print("第", index, "個元素是:", point.elem)point = point.next_print("第", (index + 1), "個元素是:", point.elem)

    思考2:如何確定循環結束的條件?


    定位元素–按下標定位

    算法描述:

  • 判斷下標的合法性
  • 根據計數器找指定下標的元素
  • 代碼實現:

    def index(self, index_):'''定位元素--按下標定位'''if index_ >= self.length() and index_ < 0:raise LinkedListUnderflow("IndexError: list index out of range")count = 0point = self._headwhile count != index_:count += 1point = point.next_return point.elem

    定位元素–按值定位

    算法描述:

  • 遍歷節點中的值匹配目標
  • 創建計數器,返回值對應的下標
  • 代碼實現:

    def find(self, val):'''定位元素--找值為x的元素'''point = self._headcount = 0# 此處需要判斷鏈表是否為空while point.elem != val and point != None:count += 1point = point.next_return count

    反轉鏈表

    算法描述:修改鏈表中節點的關系

    單鏈表反轉操作

    注意:一定要將尾節點(反轉前的首節點)的next_(鏈接域)設為None,否則會出現死循環!!!

    代碼實現:

    def rev(self):'''反轉鏈表'''point = self._headself._head = self._head.next_# 必須要將原先的首節點的next_設為0,否則將在遍歷時出現死循環point.next_ = Nonewhile self._head != None:prepoint = pointpoint = self._headself._head = self._head.next_point.next_ = prepointself._head = point

    插入

    首端插入

    算法步驟:

  • 創建一個新結點并存入數據
  • 讓新結點的鏈接域指向原鏈表首結點
  • 修改頭指針使之指向新結點
  • 思考3:能否交換上述算法步驟2、3

    算法實現:

    def prepend(self, elem):'''首端插入元素如果為空鏈表,則直接新建節點;如果為非空鏈表,則改變head指針和新節點的next_值'''n = Node(elem)if self._head == None:self._head = nelse:n.next_ = self._headself._head = n'''進階代碼1:n = Node(elem)n.next_ = self._headself._head = n進階代碼2:self._head = Node(elem, self._head)'''
    尾端插入

    算法步驟:

  • 創建一個新結點并存入數據,并將新結點的鏈接域設置為空鏈接
  • 表是否為空
  • 如果表空,直接讓頭指針指向這個新結點并結束
  • 如果表不空,找到表尾結點
  • 令表尾結點的鏈接域指向這一新結點
  • 代碼實現:

    def append(self, elem):'''尾端插入元素'''n = Node(elem)if self._head == None: # 此種情況容易疏漏self._head = nelse:point = self._headwhile point.next_ != None:point = point.next_point.next_ = n
    定位插入

    算法步驟:

  • 創建新結點并存入數據
  • 找到插入位置的前一結點
  • 修改前一結點和新結點鏈接
  • 代碼實現:

    def insert(self, index, elem):'''任意位置插入元素'''n = Node(elem)if index >= self.length() and index < 0:raise LinkedListUnderflow('insert 下標越界,不合法', i)elif index == 0:self.prepend(elem)elif index == self.length():self.append(elem)else:count = 1point = self._headwhile count != index:count += 1point = point.next_n.next_ = point.next_point.next_ = n # =================================== # 方法二:簡化def insert(self, elem, index): # 在下標為i的元素之前插入elemn = LNode(elem)if index < 0 or index >= self.length():raise LinkedListUnderflow('insert 下標越界,不合法', index)elif index == 0:self.prepend(elem)else:point = self._headwhile index != 1:index -= 1point = point.next_n.next_ = point.next_point.next_ = n

    刪除

    首部刪除

    算法步驟:

  • 判斷鏈表是否為空,若為空,則拋出異常
  • 保存首元素的地址
  • 將首指針指向下一節點
  • 返回被刪除的元素
  • 單鏈表首端刪除操作

    代碼實現:

    def pop(self):'''首端刪除并返回被刪元素'''if self._head == None:raise LinkedListUnderflow("in pop")else:n = self._head.elemself._head = self._head.next_return n
    尾部刪除

    算法步驟:

  • 判斷鏈表是否為空,若為空,則拋出異常
  • 若只有一個節點,則將首指針設為None
  • 若有兩個及以上個節點,則遍歷至倒數第二個節點
  • 設置倒數第二個節點的next_屬性(鏈接域)為None
  • 代碼實現:

    def poplast(self):'''尾端刪除并返回刪除的值'''# 空鏈表if self._head == None:raise LinkedListUnderflow("in pop last")# 只有一個元素elif self._head.next_ == None:e = self._head.elemself._head.next_ = Nonereturn e# 鏈表中有兩個或多個元素else:point = self._headwhile point.next_.next_ != None:point = point.next_e = point.next_.elempoint.next_ = Nonereturn e
    定位刪除

    算法描述:

  • 判斷鏈表是否為空,若為空,則拋出異常
  • 對索引進行合法性檢查
  • 如果索引為0,則調用pop()方法;若索引為length-1,則調用poplast()方法
  • 其余情況,通過計數器遍歷至要刪除節點的前一節點并刪除
  • 代碼實現:

    def remove(self, index):'''定位刪除'''if self._head == None:raise LinkedListUnderflow("鏈表為空")if index < 0 and index >= self.length():raise LinkedListUnderflow('remove 下標越界,不合法', i)elif index == 0:self.pop()elif index == self.length() - 1:self.poplast()else:count = 1point = self._headwhile count != index:count += 1point = point.next_e = point.next_point.next_ = point.next_.next_return e # ========================================== # 方法二:簡化def remove(self, index): #刪除下標為index的元素if self._head == None:raise LinkedListUnderflow("鏈表為空")if index < 0 or index >= self.length():raise LinkedListUnderflow('remove 下標越界,不合法', index)elif index == 0:self.pop()else:point = self._headwhile index != 1:index -= 1point = point.next_e = point.next_point.next_ = point.next_.next_return e

    思考與解答

    思考1

    為什么在遍歷鏈表時需要新建一個point變量,而不是直接用self._head去遍歷?

    因為self._head是首指針,首指針的移動會使得鏈表節點發生變化。如下圖所以,當首指針移動到第三個節點,因為第1、2個節點沒有被引用,所以這兩個節點會被Python的內存管理機制清除(刪除節點)

    思考2

    在遍歷鏈表或訪問特定的節點時,如何確定循環結束的條件?
    依據與目標節點相鄰的特殊節點的特點來設置循環條件。在遍歷操作中,我們需要遍歷到最后一個節點,最后一個節點本身就是一個特殊節點,其特點是next_(鏈接域)為None;如果需要遍歷到倒數第二個節點,同樣借助最后一個節點的特殊性。

    思考3

    在鏈表中插入元素時能否先將首節點或上一節點的指針先指向新節點?
    不能,如果將首節點或上一節點的指針指向新節點,那么后面的節點會失去引用,即被刪除



    參考文章:

  • 《數據結構與算法Python語言描述》裘宗燕
  • 老師整理ppt
  • Python內存管理機制:沒白熬夜,終于把Python的內存管理機制搞明白了
  • 總結

    以上是生活随笔為你收集整理的实现单链表--Python的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。