單鏈表及python代碼實現

1 單鏈表

單鏈表由兩部分組成:元素域與鏈接域。 元素域保存作爲表元素的數據項,鏈接域保存同一個表裏的下一個結點的標識。
圖1.1 單鏈表的結點和單鏈表
單鏈表有以下特點:

  • 一個單鏈表由一些具體的表結點組成;
  • 每個結點是一個對象,由自己的標識,也稱爲該結點的鏈接;
  • 結點之間通過結點鏈接建立起單向的順序鏈接;
  • 在python中,通常用None值作爲單鏈表中最後一個結點的鏈接域。
    爲方便討論,現在定義一個簡單的表結點類:
class LNode:
    def __init__(self,elem,next_=None):
        self.elem=elem
        self.next=next_

1.1 基本鏈表操作

1.1.1 創建空鏈表:只需要把表頭變量設置成空鏈接,在python語言中設置成爲None。
1.1.2 刪除鏈表:應丟棄這個鏈表裏的所有結點。在python語言中,只需要將表指針賦值爲None,就拋棄了鏈表中的所有結點。python解釋器的存儲管理系統會自動回收不用的存儲。
1.1.3 判斷表是否爲空:將表頭變量的值與空鏈接比較,在python語言中,就是檢查相應的變量是否爲None。
1.1.4 判斷表是否會滿:一般而言鏈表不會滿。

1.2 加入元素

1.2.1 表首端插入: 三步即可完成:

  • 創建一個新節點並存入數據;
  • 把原鏈表首節點的鏈接域存入新結點的鏈接域next。
  • 修改表頭變量,使之指向新節點。
    這裏寫圖片描述
    示例代碼段:
q=LNode(13)
q.next=head.next
head=q

1.2.2 表中間元素的插入(包括鏈表末尾插入): 設變量pre已指向要插入元素位置的歉前一結點,操作也分爲三步:

  • 創建一個新節點並存入數據;
  • 把pre所指結點的next域的值存入新節點的鏈接域next;
  • 修改pre的next域,使之指向新結點;
    這裏寫圖片描述
    示例代碼段
q=LNode(12)
q.next=pre.next
pre.next=q

1.3 刪除元素

1.3.1 刪除表首元素:刪除表中第一個元素對應於刪除表的第一個結點,爲此只需要修改表頭指針,令其指向表中的第二個結點。
示例代碼段

head=head.next

1.3.2 一般元素的情況刪除:一般情況刪除須先找到刪除元素所在結點的前一結點,設用變量pre指向,然後修改pre的next域,使之指向被刪除域的下一結點。
示例代碼段

pre.next=pre.next.next

這裏寫圖片描述

1.4 掃描、定位和遍歷

1.4.1 掃描:由於單鏈表只有一個方向的鏈接,開始情況下只有表頭變量在掌握中,所以對錶的內容的檢查只能從表頭變量開始,沿着表中鏈接逐步進行。這種行爲稱之爲鏈表的掃描。

  • 按下標定位:按Python慣例,鏈表首結點的元素應看做下標爲0,其他元素依次排列,確定第i個元素所在結點的操作稱爲按下標定位。代碼示例段如下:
p=head
while p is not None and i > 0:
    i-=1
    p=p.next
  • 按元素定位:假設在鏈表中需要找到滿足謂詞pred的元素,示例代碼段如下:
p=head
while p is not None and not pred(p.elem):
    p=p.next
  • 完整的遍歷
p=head
while p is not None:
    print p.elem
    p=p.next

1.5 鏈表操作的時間複雜度

  • 創建空表:O(1)
  • 刪除表:O(1)
  • 判斷空表:O(1)
  • 加入元素(都需要加一個T()分配時間):
  • 首端加入元素,O(1)
  • 尾端加入元素,O(n)
  • 定位加入元素,O(n),平均情況和最壞情況
  • 刪除元素:
  • 首端刪除元素:O(1)
  • 尾端刪除元素:O(n)
  • 定位刪除元素:O(n),平均情況和最壞情況
  • 其他刪除:通常需要掃描整個表或其一部分

1.6 LList類的定義,初始化函數和簡單操作

現在基於結點類LNode定義一個單鏈表類,只有一個引用鏈接結點的_head域,初始化爲None表示建立的是一個空表。

class LList:
    def __init__(self):
        self._head=None

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

    #insert element on the beginning of the list    
    def prepend(self):           
         self._head=LNode(elem,self._head)

    def pop(self):
        if self._head is None:   #if list is none, raise exception
            raise Error
        e=self._head.elem
        self._head=self._head.next
        return e

    # insert element on the end of the List
    def append(self,elem):
        if self._head is None:
            self._head=LNode(elem)
            return 
        p=self._head
        while p is not None:
            p=p.next
        p.next=LNode(elem)

    # delete the last node and return it's value
        def pop_last(self):
            if self._head is None:
                raise ExceptionError
            p=self._head
            if p.next is None:
                e=p.elem
                self._head=None
                return e
            while p.next.next is not None:
                p=p.next
            e=p.next.elem
            p.next=None
            return e
    #basic scan element in the List
    def find(self,pred):
        p=self._head
        while p is not None:
            if pred(p.elem):
                return p.elem
            p=p.next
    # print all elem in the list
    def printall(self):
        p=self._head
        while p is not None:
            print p.elem 
            if p.next is not None:
                print ','
            p=p.next
        print ''
參考文獻

裘宗燕 . 數據結構與算法:Python語言描述[M]. 北京:機械工業出版社,2016:80-88.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章