def test_list_appends_x(): l = LinkedList() l.append(1) l.append(2) l.append(3) assert len(l) == 3 assert list(l) == [1, 2, 3]
def build_two_list_with_common_nodes(seq1, seq2, common_nodes=None): if seq1 is None and seq2: return List.fromvalues(seq2).head if seq1 and seq2 is None: return List.fromvalues(seq1).head l1 = List.fromvalues(seq1) l2 = List.fromvalues(seq2) if common_nodes is None or len(common_nodes) < 1: return l1.head, l2.head last_node1 = l1.find_node(l1[-1]) last_node2 = l2.find_node(l2[-1]) l1.head.val += len(common_nodes) l2.head.val += len(common_nodes) common_node = Node(common_nodes[0], None) last_node1.next = common_node last_node2.next = common_node for x in common_nodes[1:]: common_node.next = Node(x, None) common_node = common_node.next return l1.head, l2.head
def remove_duplicates(data): if data is None: return None if len(data) == 0: return [] head = List.fromvalues(data).head return list(List.fromhead(_remove_duplicates(head)))
def test_lists_are_equal(): l1 = LinkedList.fromvalues([1, 2, 3, 4]) with pytest.raises(TypeError): assert l1 == [1, 2, 3, 4] l2 = LinkedList.fromvalues([1, 2, 3]) assert l1 != l2 l3 = LinkedList.fromvalues([1, 2, 3, 4]) assert l1 == l3
def delete(data, val): if data is None: return None if len(data) == 0: return [] head = List.fromvalues(data).head p = head.next while p and p.val != val: p = p.next return list(List.fromhead(_delete_node(head, p)))
def test_list_removes_x(): l = LinkedList.fromvalues([1, 2, 3, 4, 5, 6]) l.remove(1) assert 5 == len(l) assert 1 not in l with pytest.raises(ValueError): l.remove(10)
def test_visit_linkedlist_reversely(visit_func, seq, expect): assert visit_func(None) is None output = StringIO() with redirect_stdout(output): head = List.fromvalues(seq).head.next visit_func(head) assert output.getvalue().strip() == expect.strip()
def test_list_indexes_x(): l = LinkedList.fromvalues([1, 2, 3, 4, 5, 6]) assert 0 == l.index(1) assert 5 == l.index(6) assert 5 == l.index(6, 5) with pytest.raises(ValueError): l.index(12) with pytest.raises(ValueError): l.index(1, 2)
def test_list_inserts_x(): l = LinkedList.fromvalues([1]) l.insert(0, 2) assert len(l) == 2 assert [2, 1] == list(l) l.insert(3, 3) assert len(l) == 3 assert [2, 1, 3] == list(l) l.insert(100, 100) assert [2, 1, 3, 100] == list(l)
def merge_two_sorted_list(values_left, values_right): """这个是一个典型的递归过程 原则是谁小谁做最终链表的头,这样整个递归完成后,就得到有序的 链表了。 """ left_head = List.fromvalues(values_left).head right_head = List.fromvalues(values_right).head # 考虑特殊情况 if left_head is None: return right_head elif right_head is None: return left_head if left_head is None and right_head is None: return None # 指向真正的头节点 merged_head = Node(None, None) def merge(left, right): if left is None: return right elif right is None: return left # 谁小谁做头 if left.val > right.val: head = right head.next = merge(left, right.next) else: head = left head.next = merge(left.next, right) return head merged_head.next = merge(left_head.next, right_head.next) return merged_head
def build_partial_circular_list(values, entry_value): """构建部分环形的链表""" if values is None: return None values = List.fromvalues(values) if entry_value is not None: # 查找 entry 节点 entry_node = values.find_node(entry_value) last_node = values.find_node(values[-1]) last_node.next = entry_node return values.head
def test_list_pops_item(): l = LinkedList.fromvalues([1, 2, 3, 4, 5, 6]) assert 1 == l.pop(0) assert len(l) == 5 assert 6 == l.pop() assert len(l) == 4 # [2, 3, 4, 5] assert 3 == l.pop(1) assert 4 == l.pop(-2) assert 5 == l.pop() assert 2 == l.pop() with pytest.raises(IndexError): l.pop()
def _(*args, **kwargs): head = func(*args, **kwargs) if head is not None: return list(List.fromhead(head)) return None
while q and steps > 0: q = q.next steps -= 1 # 二者一起往后走,直到遇到相同的节点 while p and q: if p is q: return p.val p = p.next q = q.next return None def _get_length(head): if head is None: return 0 return head.val if __name__ == '__main__': h1, h2 = build_two_list_with_common_nodes([1, 2], [4, 5, 6], common_nodes=[10, 11, 12]) print(List.fromhead(h1)) print(List.fromhead(h2)) print(find_first_common_node_2(h1, h2)) print(_get_length(h1))
def test_find_kth_node(seq, k, expected): head = List.fromvalues(seq).head if seq else None if expected is None: assert find_kth_node(head, k) is None else: assert find_kth_node(head, k).val == expected
def test_list_contains_x(): values = [1, 2, 3, 4] l = LinkedList.fromvalues(values) assert 1 in l assert 3 in l assert 10 not in l
def test_create_linked_list_from_values(): values = [1, 2, 3, 4] l = LinkedList.fromvalues(values) assert list(l) == values assert len(l) == len(values)
if head is None: return None visit_linkedlist_reversely1(head.next) print(head.val, end=' ') def visit_linkedlist_reversely2(head): """利用一个栈结构存储节点,避免递归深度过大导致可能的栈溢出问题,提高 程序的鲁棒性""" if head is None: return None from collections import deque nodes = deque() while head is not None: nodes.append(head.val) head = head.next while len(nodes) > 0: print(nodes.pop(), end=' ') if __name__ == '__main__': from src.datastructures.linkedlist.single import List l = List.fromvalues([1, 2, 3, 4]) visit_linkedlist_reversely1(l.head.next) visit_linkedlist_reversely2(l.head.next)
def test_reverse_list(values, reversed_values): l = LinkedList.fromvalues(values) l.reverse() assert list(l) == reversed_values
if head is None: return None if k < 1: return None behind, ahead = head.next, head.next for _ in range(k - 1): # 头指针先走 k -1 步 ahead = ahead.next if ahead is None: # 防止走过头了,可能链表长度不够 return None # 前后指针共同往后走 while ahead.next: ahead = ahead.next behind = behind.next # behind 所指向的就是相应的节点 return behind if __name__ == '__main__': from src.datastructures.linkedlist.single import List l = List.fromvalues([1]) print(find_kth_node(l.head, 1))