循環鏈表
當要處理的數據具備環形結構的時候, 適合循環鏈表. 如約瑟夫環問題node
雙向循環鏈表python
數組的缺點是大小固定, 一旦聲明長度就要佔用連續的內存空間, 當空間不夠用時更換更大的空間, 此時就須要將原數組的全部數據遷移過去, 比較費時. 鏈表則能夠動態擴容.算法
數組在查詢上能夠更快, 鏈表在插入和刪除上更快, 爲告終合數組和鏈表的優勢, 有同時使用的狀況, 好比一個網站的用戶註冊, 能夠以A-Z
爲數組, 在每一個字母后面加入鏈表, 這樣能夠在添加新用戶的時候能快速找到要添加的鏈表並進行插入, 同時在查詢用戶的時候也能縮短查詢時間數組
""" 單鏈表 """ class Node(object): def __init__(self, data, next_=None): self.data = data self.next_ = next_ class SingleLinkedList(object): def __init__(self): self.head = None def is_empty(self): return self.head == None def size(self): current = self.head num = 0 while current != None: current = current.next_ num += 1 return num def prepend(self, value): """ 在頭部添加節點 :param value: :return: """ self.head = Node(value, self.head) def append(self, value): """ 在尾部追加節點 :param value: :return: """ node = Node(value) if self.is_empty(): self.head = node else: current = self.head while current.next_ != None: current = current.next_ current.next_ = node def insert(self, position, value): """ 指定位置插入節點, 從1開始計數 :param position: :param value: :return: """ if position <= 1: self.prepend(value) elif position > self.size(): self.append(value) else: node = Node(value) tmp_pos = 1 pre_node = None current = self.head while tmp_pos < position: pre_node = current current = current.next_ tmp_pos += 1 node.next_ = current pre_node.next_ = node def delete(self, value): if self.is_empty(): raise Exception("empty") pre_node = None current = self.head while current != None: if current.data == value: # 判斷刪除的元素是否是第一個 if not pre_node: self.head = current.next_ else: pre_node.next_ = current.next_ break else: pre_node = current current = current.next_ def pop_first(self): if self.is_empty(): raise Exception("empty") data = self.head.data self.head = self.head.next_ return data def pop_last(self): if self.is_empty(): raise Exception("empty") pre_node = None current = self.head while current.next_ != None: pre_node = current current = current.next_ data = current.data if pre_node == None: self.head = None else: pre_node.next = None return data def find(self, value): status = False current = self.head while current != None and not status: if current.data == value: status = True else: current = current.next_ return status
# coding:utf-8 """ 單鏈表反轉 """ class Node(object): def __init__(self, data, next_=None): self.data = data self.next_ = next_ def reverse(linked_list): head = linked_list pre = None while head != None: current = head head = current.next_ current.next_ = pre pre = current return pre def output(linked_list): current = linked_list res = [] while current != None: res.append(current.data) current = current.next_ print(res) if __name__ == '__main__': link = Node(1, Node(2, Node(3, Node(4, Node(5, Node(6, Node(7, Node(8, Node(9))))))))) output(link) root = reverse(link) output(root) """ [1, 2, 3, 4, 5, 6, 7, 8, 9] [9, 8, 7, 6, 5, 4, 3, 2, 1] """
# coding:utf-8 """ 鏈表成對調換 1 -> 2 -> 3 -> 4 調換後爲 2 -> 1 -> 4 -> 3 """ class Node(object): def __init__(self, data, next_=None): self.data = data self.next_ = next_ def swap(head): if head != None and head.next_ != None: after = head.next_ head.next_ = swap(after.next_) after.next_ = head return after return head def output(linked_list): current = linked_list res = [] while current != None: res.append(current.data) current = current.next_ print(res) if __name__ == '__main__': link = Node(1, Node(2, Node(3, Node(4)))) output(link) print('----') link1 = swap(link) output(link1) """ [1, 2, 3, 4] ---- [2, 1, 4, 3] """
sub_size
sub_size
步定義兩個遊標first和later, first步長是1, later步長是2. 同時向前走, 若是有環必定會遇到. 複雜度O(n)數據結構
# -*- coding:utf-8 -*- """ 判斷鏈表是否有環 """ class Node(object): def __init__(self, data, next_=None): self.data = data self.next_ = next_ def check(head): current1 = current2 = head while True: current1 = current1.next_ # 指向第一個節點 current2 = current2.next_.next_ # 指向第二個節點 if (not current1) or (not current2): break if current1.data == current2.data: return True return False if __name__ == '__main__': node1 = Node(6) node2 = Node(2) node3 = Node(3) node4 = Node(4) node5 = Node(5) node6 = Node(6) node1.next_ = node2 node2.next_ = node3 node3.next_ = node4 node4.next_ = node5 node5.next_ = node6 node6.next_ = node3 # 環交點 assert check(node1) == True
定義兩個指針first, later都初始化指向頭節點, 而後first先走k步, 再同時走, 當first到尾節點的時候, 讀出later節點的值. 複雜度是O(n)app
# -*- coding:utf-8 -*- """ 找到鏈表的倒數第K個元素 定義兩個遊標, 第二個遊標先走k-1步, 以後再同時走, 此時第一個遊標停留位置就是倒數第K個元素 """ class Node(object): def __init__(self, data, next_=None): self.data = data self.next_ = next_ def find_reverse_k(head, k): c1 = head current = head for _ in range(k - 1): current = current.next_ c2 = current while c2.next_ != None: c2 = c2.next_ c1 = c1.next_ return c1.data if __name__ == '__main__': link = Node(1, Node(2, Node(3, Node(4, Node(5, Node(6, Node(7, Node(8, Node(9))))))))) assert find_reverse_k(link, 3) == 7 assert find_reverse_k(link, 1) == 9 assert find_reverse_k(link, 2) == 8
# coding:utf-8 """ 合併兩個有序單鏈表 輸入:1->2->4, 1->3->4 輸出:1->1->2->3->4->4 """ class Node(object): def __init__(self, data, next_=None): self.data = data self.next_ = next_ def merge2linkedlist(l1, l2): """ 合併兩個有序鏈表 :param l1: :param l2: :return: """ if l1 == None and l2 == None: raise Exception("None!!!") if l1 == None: return l2 if l2 == None: return l1 # 使用head爲輔助節點 head = Node(0) current = head while l1 and l2: if l1.data <= l2.data: current.next_ = l1 l1 = l1.next_ elif l1.data > l2.data: current.next_ = l2 l2 = l2.next_ current = current.next_ if l1: current.next_ = l1 if l2: current.next_ = l2 return head.next_ if __name__ == "__main__": l1 = Node(1, Node(2, Node(4))) l2 = Node(1, Node(3, Node(4))) tmp = merge2linkedlist(l1, l2) res = [] while tmp: res.append(tmp.data) tmp = tmp.next_ print(res) """ [1, 1, 2, 3, 4, 4] """
咱們說空間複雜度的時候, 是指除了本來的數據存儲空間外, 算法還須要的額外的存儲空間, 即無論原來所佔空間是多少網站