算法與數據結構(part6)--單向鏈表

學習筆記,僅供參考,有錯必糾

參考自:單鏈表頭指針、頭結點、頭元結的辨析



算法與數據結構–基於python


鏈表


爲啥需要鏈表


順序表的構建需要預先知道數據大小來申請連續的存儲空間,而在進行擴充時又需要進行數據的搬遷,所以使用起來不是很靈活;而鏈表結構可以充分利用計算機內存空間,實現靈活的內存動態管理


什麼是鏈表


鏈表結構可以充分利用計算機內存空間,實現靈活的內存動態管理,鏈表是一種常見的基礎數據結構,是一種線性表,但是不像順序表一樣連續存儲數據,而是在每一個結點(數據存儲單元)裏存放下一個結點的位置信息(即地址)


單向鏈表


什麼是單向鏈表


單向鏈表也叫單鏈表,是鏈表中最簡單的一種形式;它的每個結點包含兩個域,一個信息域(元素域)和一個鏈接域;這個鏈接指向鏈表中的下一個結點,而最後一個結點的鏈接域則指向一個空值。


  • 圖示

單鏈表也可以沒有頭結點,如果沒有頭結點的話,那麼單鏈表就會變成這樣:

  • 關於頭結點

頭結點是爲了操作的統一與方便而設立的,放在第一個元素結點之前,其數據域一般無意義(當然有些情況下也可存放鏈表的長度、用做監視哨等等),首元結點也就是第一個元素的結點,它是頭結點後邊的第一個結點,頭結點不是鏈表所必需的


  • 關於頭指針

在線性表的鏈式存儲結構中,頭指針是指鏈表指向第一個結點的指針,若鏈表有頭結點,則頭指針就是指向鏈表頭結點的指針;頭指針具有標識作用,故常用頭指針冠以鏈表的名字;無論鏈表是否爲空,頭指針均不爲空,頭指針是鏈表的必要元素


單列表的操作


is_empty()
#鏈表是否爲空
length()
#鏈表長度
travel()
#遍歷整個鏈表
append(item)
#鏈表尾部添加元素
add(item)
#鏈表頭部添加元素
insert(pos, item)
#指定位置添加元素
search(item)
#查找結點是否存在
remove(item)
#刪除結點

節點的實現


class Node:
    def __init__(self, elem):
        #初始化數據區
        self.elem = elem
        #初始化鏈接區
        self.next = None

單鏈表的實現


首先,我們參照下圖中的鏈表形式,來構造我們的單鏈表:

同時,我們參照下圖中的尾插法,在我們的鏈表末尾插入數據:

參照下圖中的頭插法,在鏈表頭部添加元素:

參照下圖中的插入法,在鏈表中指定位置插入元素:

參照下圖中的刪除法,在鏈表中刪除某個指定元素:


定義單鏈表:

class SingleLinkedList:
    def __init__(self):
        #頭指針
        self.__head = None
    
    #判斷鏈表是否爲空
    def is_empty(self):
        return self.__head is None
    
    #查詢長度
    def length(self):
        #判斷是否爲空
        if self.is_empty():
            return 0
        else:
            #定義遊標
            cur = self.__head
            #計數
            count = 0
            while cur != None:
                cur = cur.next
                count += 1
            return count
        
    #遍歷鏈表
    def travel(self):
        if self.is_empty():
            return
        else:
            #定義遊標
            cur = self.__head
            while cur != None:
                #打印數據
                print(cur.elem, " ")
                cur = cur.next
            print('')
    
    #鏈表尾部添加元素
    def append(self, item):
        #定義新節點
        node = Node(item)
        
        #判斷鏈表是否爲空
        if self.is_empty():
            self.__head = node
        else:
            cur = self.__head
            while cur.next!= None:
                cur = cur.next
            #while循環結束後,cur到達了最後一個節點
            cur.next = node
            
    #鏈表開頭插入
    def add(self, item):
        #新節點
        node = Node(item)
        if self.is_empty():
            self.__head = node
        else:
            node.next = self.__head
            self.__head = node
            
    #鏈表中指定位置插入
    def insert(self, pos, item):
        #新節點
        if pos < 0:
            self.add(item)
        elif pos > (self.length() - 1):
            self.append(item)
        else:
            node = Node(item)
            pre = self.__head
            count = 0
            
            while count < (pos -1):
                pre = pre.next
                count += 1
            #下面的兩行代碼順序不可變
            node.next = pre.next
            pre.next = node
    #查找節點
    def search(self, item):
        if self.is_empty():
            return False
        else:
            cur = self.__head
            while cur!= None:
                if cur.elem == item:
                    return True
                else:
                    cur = cur.next
            return False
        
    #刪除節點
    def remove(self,item):
        if self.is_empty():
            return
        else:
            # 定義cur遊標
            cur = self.__head
            # 定義pre遊標
            pre = None
            # 查找所有的位置有沒有要刪除的,若有則刪
            while cur != None:
                # 判斷cur指向的數據,是否爲要刪的數據
                if cur.elem == item:
                    # 考慮特殊情況,恰好要刪的是第一個元素
                    if cur == self.__head:
                        # 頭結點指向後一個結點
                        self.__head = cur.next
                    else:
                        # 刪除
                        pre.next = cur.next
                    return
                else:
                    # 移動遊標,先移動pre,再移動cur
                    pre = cur
                    cur = cur.next

測試:

if __name__ == "__main__":
    sll = SingleLinkedList()
    print(sll.is_empty())
    print(sll.length())
    print('-'*20)
    sll.travel()
    print('-'*20)
    sll.append(1)
    sll.add(2)
    sll.append(3)
    sll.travel()
    print('-'*20)
    print(sll.is_empty())
    print(sll.length())
    print('-'*20)
    sll.insert(1,'abc')
    sll.travel()
    print(sll.search(2))
    print('-'*20)
    sll.remove('abc')
    sll.travel()

輸出:

True
0
--------------------
--------------------
2  
1  
3  

--------------------
False
3
--------------------
2  
abc  
1  
3  

True
--------------------
2  
1  
3  

鏈表與順序表的對比


鏈表與順序表各種操作的時間複雜度:

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

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