1. 程式人生 > >兩種連結串列操作--連結串列反轉、連結串列排序(pyhon實現)

兩種連結串列操作--連結串列反轉、連結串列排序(pyhon實現)

連結串列反轉和連結串列排序是兩種連結串列的基本操作,在python裡list型別的reverse()方法就是對list的反轉,sort()方法可以對list的元素進行排序,本文將探討這兩種連結串列操作基於單鏈表的實現方式。

連結串列反轉

對於單鏈表而言,連結串列反轉可以有兩種實現方式,一種是在節點之間搬動元素,即往復地將尾部元素搬到頭部;另一種是修改節點的連線關係,通過改變節點的連線順序來改表元素的順序。但是單鏈表不支援從尾部向前查詢元素,如果採用搬動元素的方法,則效率很低(O(n^{}2))。因此考慮第二種實現方式。注意到連結串列在頭部插入節點或刪除節點花費的時間都是O(1),如果不斷從連結串列的頭部取下節點,插入到另一個連結串列的頭部,這樣最後得到的就是反轉後的連結串列,並且這是一個高效的操作,花費時間為O(n)。

    def rev(self):
        p=None
        while self._head is not None:
            q=self._head
            self._head=q.next    #取下原來的首節點
            q.next=p
            p=q                  #將剛取下的節點加入p引用的節點序列
        self._head=p             #反轉後的節點序列已經做好,重置表頭連線

在實際生活中也經常能見到類似的過程,如通過排程把一列火車車廂的順序顛倒過來。另外,如果桌上有一摞書,一本本拿下來放到另一處,疊成另一摞,也是這個操作的例項。 

連結串列排序

排序演算法有很多種,本結主要討論基於插入排序的連結串列排序,插入排序的原理大家可以自行查詢,這裡不再贅述。主要實現有兩種方式:1.基於移動元素的連結串列排序,2.基於調整連結串列的連結串列排序。

  • 基於移動元素的連結串列排序

如圖a)所示,在第i個節點d之前的連結串列節點元素都是已排序的,現在要將d插入前面的有序序列中。採用移動元素的方法,從頭結點開始掃描該有序序列直到找到第一個大於d的節點位置,記為j。然後將j及j之後的元素依次後移,最後將d插入到j的位置。如此迴圈取出連結串列的元素做此操作,即可完成連結串列的排序。

 

#基於移動元素的連結串列排序
    def sort1(self):
        if self._head is None:
            return
        crt=self._head.next #從頭結點之後開始處理
        while crt is not None:
            x=crt.elem
            p=self._head
            while p is not crt and p.elem<=x:   #跳過小於它的元素
                p=p.next
            while p is not crt: #找到插入的位置,插入並且大於它的元素後移
                y=p.elem
                p.elem=x
                x=y
                p=p.next
            crt.elem=x
            crt=crt.next
  • 基於調整連結串列的連結串列排序

這種方法的操作過程比較好理解,就是一個個取下連結串列結點,將其插人一段元素遞增的結點鏈中的正確位置。

#基於調整連結串列的連結串列排序
    def sort2(self):
        p=self._head
        if p is None or p.next is None: #連結串列為空或只有一個節點,不需要排序
            return
        rem=p.next
        p.next=None
        while rem is not None:
            p=self._head
            q=None
            while p is not None and p.elem<=rem.elem:
                q=p
                p=p.next        #尋找插入位置
            if q is None:
                self._head=rem  #rem是最小的,頭部插入
            else:
                q.next=rem #q和p中間插入
            q=rem
            rem=rem.next
            q.next=p