資料結構(三)單向迴圈連結串列的的分析與python程式碼實現
阿新 • • 發佈:2019-01-11
概念
單鏈表的一個變形是單向迴圈連結串列,連結串列中最後一個節點的next域不再為None,而是指向連結串列的頭節點。
節點包含兩個域:元素域和連結域(下一個節點),尾節點next指向第0個節點,當連結串列只有一個節點時,自己的next指向自己,基於單鏈表的基礎上,增加考慮首節點和尾節點的情況。
結構
python程式碼實現
class Node(object): def __init__(self, item): self.item = item self.next = None class CycleLinkList(object): def __init__(self): self.head = None def is_empty(self): """連結串列是否為空""" return self.head is None def length(self): """連結串列長度""" if self.is_empty(): return 0 cur = self.head n = 1 while cur.next != self.head: n += 1 cur = cur.next # 至此除了尾節點外,所有節點都被數了一次 return n def travel(self): """遍歷整個連結串列""" if self.is_empty(): return cur = self.head while cur.next != self.head: print(cur.item,end="->") cur = cur.next # 至此,cur指向尾節點,cur本身還未被列印 print(cur.item) def add(self, item): """連結串列頭部新增元素""" node = Node(item) # 若沒有尾節點(連結串列為空),head指向新節點,新節點next指向自己 if self.is_empty(): self.head = node node.next = node else: # 1 找到尾節點cur cur = self.head while cur.next != self.head: cur = cur.next # 至此,cur指向尾節點 #2 新節點next指向原首節點 node.next = self.head #3 head指向新節點 self.head = node #4 尾節點next指向新節點 cur.next = node def append(self, item): """連結串列尾部新增元素""" # 若連結串列為空,則直接頭部新增 if self.is_empty(): self.add(item) return # 1 遍歷查詢尾節cur cur = self.head while cur.next != self.head: cur = cur.next # 至此cur指向當前連結串列的尾節點 # 2 cur的next指向新節點 node = Node(item) cur.next = node # 3 新節點next指向首節點 node.next = self.head def insert(self, pos, item): """指定位置新增元素""" if pos <=0 : self.add(item) elif pos >= self.length(): self.append(item) else: # 1 遍歷查詢帶插入位置的前一個節點cur cur = self.head for i in range(pos - 1): cur = cur.next # 至此,cur指向的就是帶插入位置的前一個節點 # 2 新節點的next指向cur的next node = Node(item) node.next = cur.next # 3 cur的next指向新節點 cur.next = node def remove(self, item): """刪除節點""" if self.is_empty(): return cur = self.head pre = None # 1 遍歷查詢找到待刪節點並記錄前一個節點 while cur.next != self.head: if cur.item == item: # 2 若有前一個節點,pre的next指向cur的next if pre is not None: pre.next = cur.next else: # 否則(待刪節點是首節點), # 1)遍歷查詢尾節點tail tail = self.head while tail.next != self.head: tail = tail.next # 2) head指向cur的next self.head = cur.next # 3) tail的next指向head tail.next = self.head return pre = cur cur = cur.next # 至此cur指向尾節點,尾節點還未判斷是否是待刪節點 # 3 判斷尾節點是否是待刪節點 if cur.item == item: # 若有前一個節點,pre的next指向cur的next if pre is not None: pre.next = cur.next # 否則(待刪節點是連結串列唯一節點),head指向None else: self.head = None def search(self, item): """查詢節點是否存在""" if self.is_empty(): return False cur = self.head while cur.next != self.head: if cur.item == item: return True cur = cur.next # 至此,除了尾節點外所有節點都找過了,還沒找到 # 判斷尾節點是否是待查節點 if cur.item == item: return True return False # 測試程式碼 if __name__ == '__main__': cl = CycleLinkList() cl.add(1) cl.add(2) cl.add(3) cl.travel() # 結果3-2-1- cl.append("abc") cl.append("def") cl.append("ghi") cl.travel() # 結果3-2-1-abc-def-ghi- cl.insert(-1, "xx") cl.insert(99, "yy") cl.insert(3, "zz") cl.travel() # 結果xx-3-2-zz-1-abc-def-ghi-yy- cl.remove("xx") cl.remove("yy") cl.remove(1) cl.remove(90) cl.travel() # 結果3-2-zz-abc-def-ghi- print(cl.search(3)) # 結果True print(cl.search("zz")) # 結果True print(cl.search(380)) # 結果False
複雜度
迴圈連結串列頭部新增O(n),迴圈連結串列尾部新增O(n),迴圈連結串列中間位置新增O(n),迴圈連結串列刪除O(n)。