1. 程式人生 > >資料結構之單向連結串列----python實現

資料結構之單向連結串列----python實現

單向連結串列

單向連結串列也叫單鏈表,是連結串列中最簡單的一種形式,它的每個節點包含兩個域,一個資訊域(元素域)和一個連結域。這個連結指向連結串列中的下一個節點,而最後一個節點的連結域則指向一個空值。


  • 表元素域elem用來存放具體的資料。
  • 連結域next用來存放下一個節點的位置(python中的標識)
  • 變數p指向連結串列的頭節點(首節點)的位置,從p出發能找到表中的任意節點。

節點實現

class Node():
    """結點類"""
    def __init__(self,elem):
        #存放元素資料
        self.elem=elem
        #next是下一個節點的標識
        self.next=None

單鏈表的操作

  • is_empty() 連結串列是否為空
  • length() 連結串列長度
  • travel() 遍歷整個連結串列
  • add(item) 連結串列頭部新增元素
  • append(item) 連結串列尾部新增元素
  • insert(pos, item) 指定位置新增元素
  • remove(item) 刪除節點
  • search(item) 查詢節點是否存在

單鏈表的實現

class Single_LinkList():
    def __init__(self,node=None):
        #頭節點定義為私有變數
        self._head=node

    def is_empty(self):
    #判斷連結串列是否為空
        if self._head is None:
            return True
        else:
            return False

    def length(self):
    #返回連結串列的長度
    # cur遊標,用來移動遍歷節點
    # count用來計數
        cur=self._head
        count = 0
        while cur !=None:
            count+=1
            cur=cur.next
        return count

    def travel(self):
    #遍歷整個連結串列
        cur=self._head
        while cur!=None:
            print(cur.elem,end=' ')
            cur=cur.next
        print()

頭部新增元素


    def add(self,item):
    #在頭部新增一個節點
        # 先建立一個儲存item值的節點
        node=Node(item)
        #判斷連結串列是否為空
        if self._head==None:
            self._head=node
        else:
            # 將新節點的連結域next指向頭節點,即_head指向的位置
            node.next=self._head
            # 將連結串列的頭_head指向新節點
            self._head=node

尾部新增元素

    def append(self,item):
    #在尾部新增一個節點
        node=Node(item)
        #若連結串列為空,直接將該節點作為連結串列的第一個元素
        if self._head==None:
            self._head=node
        else:
            cur = self._head
            while cur.next !=None:
                cur=cur.next
            cur.next=node

指定位置新增元素


    def insert(self,pos,item):
    #在指定位置pos新增節點
    #pos從0開始
    # 若指定位置pos為第一個元素之前,則執行頭部插入
        if pos<=0:
            self.add(item)
        # 若指定位置超過連結串列尾部,則執行尾部插入
        elif pos>=self.length():
            self.append(item)
        # 找到指定位置
        else:
            # pre用來指向指定位置pos的前一個位置pos-1,初始從頭節點開始移動到指定位置
            pre=self._head
            count=0
            node = Node(item)
            while count<(pos-1):
                count+=1
                pre=pre.next
            # 先將新節點node的next指向插入位置的節點
            node.next=pre.next
            # 將插入位置的前一個節點的next指向新節點
            pre.next=node

刪除節點


    def remove(self,item):
    #刪除某一個節點
        # 若連結串列為空,則直接返回
        if self.is_empty():
            return
        pre=None
        cur=self._head

        while cur!=None:
            #若沒有找到元素,繼續按連結串列後移節點
            if cur.elem!=item:
                pre=cur
                cur=cur.next
            else:
                #若要刪除的點為頭節點
                if cur==self._head:
                    self._head=cur.next
                    #刪完要break,不然陷入死迴圈
                    break
                else:
                #要刪除的點不是頭節點
                    pre.next=cur.next
                    break

查詢節點是否存在

    def search(self,item):
    #查詢節點是否存在
        cur=self._head
        while cur!=None:
            if cur.elem==item:
                return True
            else:
                cur = cur.next
        return False
測試
if __name__ == '__main__':
    single_obj=Single_LinkList()
    print(single_obj.is_empty())
    print(single_obj.length())
    single_obj.append(1)
    single_obj.append(2)
    single_obj.append(3)
    single_obj.append(4)
    single_obj.append(5)
    single_obj.travel()
    single_obj.add(-1)
    single_obj.travel()
    single_obj.insert(-1,-2)
    single_obj.travel()
    single_obj.insert(2,0)
    single_obj.travel()
    print(single_obj.search(0))
    single_obj.remove(2)
    single_obj.travel()
True
0
1 2 3 4 5 
-1 1 2 3 4 5 
-2 -1 1 2 3 4 5 
-2 -1 0 1 2 3 4 5 
True
-2 -1 0 1 3 4 5 

連結串列與順序表的對比

連結串列失去了順序表隨機讀取的優點,同時連結串列由於增加了結點的指標域,空間開銷比較大,但對儲存空間的使用要相對靈活。

連結串列與順序表的各種操作複雜度如下所示:

操作連結串列順序表
訪問元素O(n)O(1)
在頭部插入/刪除O(1)O(n)
在尾部插入/刪除O(n)O(1)
在中間插入/刪除O(n)O(n)

注意雖然表面看起來複雜度都是 O(n),但是連結串列和順序表在插入和刪除時進行的是完全不同的操作。連結串列的主要耗時操作是遍歷查詢,刪除和插入操作本身的複雜度是O(1)。順序表查詢很快,主要耗時的操作是拷貝覆蓋。因為除了目標元素在尾部的特殊情況,順序表進行插入和刪除時需要對操作點之後的所有元素進行前後移位操作,只能通過拷貝和覆蓋的方法進行。