数据结构和算法-链表
生活随笔
收集整理的這篇文章主要介紹了
数据结构和算法-链表
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
鏈表分類
- 單向鏈表
- 雙向鏈表
優勢:- 刪除某個節點更加高效, 可以快速找到前驅節點
- 可以方便的在某個節點前插入元素
循環鏈表
當要處理的數據具有環形結構的時候, 適合循環鏈表. 如約瑟夫環問題雙向循環鏈表
數組的缺點是大小固定, 一旦聲明長度就要占用連續的內存空間, 當空間不夠用時更換更大的空間, 此時就需要將原數組的所有數據遷移過去, 比較費時. 鏈表則可以動態擴容.
數組在查詢上可以更快, 鏈表在插入和刪除上更快, 為了結合數組和鏈表的優點, 有同時使用的情況, 比如一個網站的用戶注冊, 可以以A-Z為數組, 在每個字母后面加入鏈表, 這樣可以在添加新用戶的時候能快速找到要添加的鏈表并進行插入, 同時在查詢用戶的時候也能縮短查詢時間
常見邊界條件
- 鏈表為空
- 只有一個節點
- 只有兩個節點
- 指針在頭結點和尾節點的處理
常見問題
- 單鏈表反轉
- 檢測鏈表中是否有環
- 兩個有序鏈表合并
- 刪除鏈表倒數第n個節點
- 求鏈表的中間節點
單向鏈表
""" 單鏈表 """class Node(object):def __init__(self, data, next_=None):self.data = dataself.next_ = next_class SingleLinkedList(object):def __init__(self):self.head = Nonedef is_empty(self):return self.head == Nonedef size(self):current = self.headnum = 0while current != None:current = current.next_num += 1return numdef 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 = nodeelse:current = self.headwhile current.next_ != None:current = current.next_current.next_ = nodedef 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 = 1pre_node = Nonecurrent = self.headwhile tmp_pos < position:pre_node = currentcurrent = current.next_tmp_pos += 1node.next_ = currentpre_node.next_ = nodedef delete(self, value):if self.is_empty():raise Exception("empty")pre_node = Nonecurrent = self.headwhile current != None:if current.data == value:# 判斷刪除的元素是不是第一個if not pre_node:self.head = current.next_else:pre_node.next_ = current.next_breakelse:pre_node = currentcurrent = current.next_def pop_first(self):if self.is_empty():raise Exception("empty")data = self.head.dataself.head = self.head.next_return datadef pop_last(self):if self.is_empty():raise Exception("empty")pre_node = Nonecurrent = self.headwhile current.next_ != None:pre_node = currentcurrent = current.next_data = current.dataif pre_node == None:self.head = Noneelse:pre_node.next = Nonereturn datadef find(self, value):status = Falsecurrent = self.headwhile current != None and not status:if current.data == value:status = Trueelse:current = current.next_return status單鏈表反轉
# coding:utf-8""" 單鏈表反轉 """class Node(object):def __init__(self, data, next_=None):self.data = dataself.next_ = next_def reverse(linked_list):head = linked_listpre = Nonewhile head != None:current = headhead = current.next_current.next_ = prepre = currentreturn predef output(linked_list):current = linked_listres = []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 = dataself.next_ = next_def swap(head):if head != None and head.next_ != None:after = head.next_head.next_ = swap(after.next_)after.next_ = headreturn afterreturn headdef output(linked_list):current = linked_listres = []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步
- 最后依次比較兩條鏈表對應的值是否相等, 相等處則是交點
時間復雜度O(m+n)
判斷鏈表是否有環
定義兩個游標first和later, first步長是1, later步長是2. 同時向前走, 如果有環一定會遇到. 復雜度O(n)
# -*- coding:utf-8 -*-""" 判斷鏈表是否有環 """class Node(object):def __init__(self, data, next_=None):self.data = dataself.next_ = next_def check(head):current1 = current2 = headwhile True:current1 = current1.next_ # 指向第一個節點current2 = current2.next_.next_ # 指向第二個節點if (not current1) or (not current2):breakif current1.data == current2.data:return Truereturn Falseif __name__ == '__main__':node1 = Node(6)node2 = Node(2)node3 = Node(3)node4 = Node(4)node5 = Node(5)node6 = Node(6)node1.next_ = node2node2.next_ = node3node3.next_ = node4node4.next_ = node5node5.next_ = node6node6.next_ = node3 # 環交點assert check(node1) == True查找單鏈表倒數第k個元素
定義兩個指針first, later都初始化指向頭節點, 然后first先走k步, 再同時走, 當first到尾節點的時候, 讀出later節點的值. 復雜度是O(n)
# -*- coding:utf-8 -*-""" 找到鏈表的倒數第K個元素定義兩個游標, 第二個游標先走k-1步, 之后再同時走, 此時第一個游標停留位置就是倒數第K個元素 """class Node(object):def __init__(self, data, next_=None):self.data = dataself.next_ = next_def find_reverse_k(head, k):c1 = headcurrent = headfor _ in range(k - 1):current = current.next_c2 = currentwhile c2.next_ != None:c2 = c2.next_c1 = c1.next_return c1.dataif __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) == 7assert find_reverse_k(link, 1) == 9assert 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 = dataself.next_ = next_def merge2linkedlist(l1, l2):"""合并兩個有序鏈表:param l1::param l2::return:"""if l1 == None and l2 == None:raise Exception("None!!!")if l1 == None:return l2if l2 == None:return l1# 使用head為輔助節點head = Node(0)current = headwhile l1 and l2:if l1.data <= l2.data:current.next_ = l1l1 = l1.next_elif l1.data > l2.data:current.next_ = l2l2 = l2.next_current = current.next_if l1:current.next_ = l1if l2:current.next_ = l2return 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] """合并K個有序單鏈表
- 方法一
把K個鏈表2個為一組進行合并, 不斷分組, 最后合并為一個有序鏈表 - 方法二
遍歷所有鏈表將所有元素放在一個數組中, 然后對數組進行排序, 最后生成一個有序鏈表.
時間復雜度:
如果所有鏈表共有n個元素, 遍歷需要O(n), 對數組排序需要O(nlogn), 最后連接O(n). 所以總的復雜度是O(n + nlogn + n), 也就是O(nlogn)
注意
我們說空間復雜度的時候, 是指除了原本的數據存儲空間外, 算法還需要的額外的存儲空間, 即不管原來所占空間是多少
資料
- <>
- <>
- <>
轉載于:https://www.cnblogs.com/zlone/p/10993902.html
總結
以上是生活随笔為你收集整理的数据结构和算法-链表的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python说文解字_杂谈06
- 下一篇: Yet Another Multiple