循环链表
当要处理的数据具备环形结构的时候, 适合循环链表. 如约瑟夫环问题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] """
咱们说空间复杂度的时候, 是指除了本来的数据存储空间外, 算法还须要的额外的存储空间, 即无论原来所占空间是多少网站