defaddEdge(self, from_vertex, to_vertex): if from_vertex in self.a_list.keys(): self.a_list[from_vertex].append(to_vertex) else: self.a_list[from_vertex] = [to_vertex]
defprint_a_list(self): for from_v in self.a_list: print('{vertex} ->'.format(vertex = from_v), ' -> '.join( [str(to_v) for to_v in self.a_list[from_v]]))
tree 树
{|E| = |V| - 1}
tree
binary tree
binary search tree (BST) 二叉查找树 {math.floor(logn) <= h <= n-1}
defcontain(self, val): current = self.root while current: if current.val == val: returnTrue if val < current.val: current = current.left else: current = current.right returnFalse
publicfunccontains(_ value: Element) -> Bool { var current = root whilelet node = current { if node.val == value { returntrue } if value < node.val { current = node.left } else { current = node.right } } returnfalse }
defbalanced(self, node): if node.get_balanceFactor() == 2: if node.left and node.left.get_balanceFactor() == -1: return self.left_right_rotate(node) else: return self.right_rotate(node) if node.get_balanceFactor() == -2: if node.right and node.right.get_balanceFactor() == 1: return self.right_left_rotate(node) else: return self.left_rotate(node) return node
defcontain(self, val): current = self.root while current: if current.val == val: returnTrue if val < current.val: current = current.left else: current = current.right returnFalse
Time complexity: {Average: Θ(n^2), Worse: O(n^2), Best: Ω(n^2)}
Space complexity: {O(1)}
1 2 3 4 5 6 7
defselection_sort(list): for i in range(0, len(list) - 1): min_num = list[i] for j in range(i + 1, len(list)): min_num = min(min_num, list[j]) list[list[i:].index(min_num) + i], list[i] = list[i], min_num return list
bubble sort 冒泡排序
{对于差不多排好序的速度很快,可以到达Ω(n)}
比较相邻元素并将最大的元素向后沉直到最后,重复这个步骤
Time complexity: {Average: Θ(n^2), Worse: O(n^2), Best: Ω(n)}
Space complexity: {O(1)}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
defbubble_sort(list): for i in range(len(list) - 1): for j in range(len(list) - 1 - i): if list[j] > list[j + 1]: list[j], list[j + 1] = list[j + 1], list[j] return list defbubble_sort_upgrade(list): for i in range(len(list) - 1): already_sorted = True for j in range(len(list) - 1 - i): if list[j] > list[j + 1]: list[j], list[j + 1] = list[j + 1], list[j] already_sorted = False if already_sorted: break return list
sequential search 顺序查找 线性算法
Time complexity: {Average: Θ(n), Worse: O(n), Best: Ω(1)}
Space complexity: {O(1)}
1 2 3 4 5
defsequential_search(list, k): for i, ele in enumerate(list): if ele == k: return i return-1
dfs 深度优先查找
Time complexity: O(|V|+|E|) = O(b^{d})
Space complexity: O(|V|)
1 2 3 4 5 6 7 8 9 10
defdfs(graph, start): visited, stack, count = [], [start], 0 while stack: vertex = stack.pop() count += 1 visited.append(vertex) for v in graph[vertex]: if v notin visited + stack: stack.append(v) return visited, count
bfs 广度优先查找
Time complexity: O(|V|+|E|) = O(b^{d})
Space complexity: O(|V|) = O(b^{d})
1 2 3 4 5 6 7 8 9 10
defbfs(graph, start): visited, queue, count = [], [start], 0 while queue: vertex = queue.pop(0) count += 1 visited.append(vertex) for v in graph[vertex]: if v notin visited + queue: queue.append(v) return visited, count
Decrease-And-Conquer 减治法
insertion sort 插入排序
{对于差不多排好序的速度很快,可以到达Ω(n)}
从第二个元素开始向前找到正确的位置插入
Time complexity: {Average: Θ(n^2), Worse: O(n^2), Best: Ω(n)}
Space complexity: {O(1)}
1 2 3 4 5 6 7 8 9
definsetion_sort(list): for i in range(1, len(list)): insert_num = list[i] j = i - 1 while j >= 0and list[j] > insert_num: list[j + 1] = list[j] j -= 1 list[j+ 1] = insert_num return list
shell sort 希尔排序
通过一个gap来左插入排序(常用方法是从len/2gap开始每次缩小2倍)
Time complexity: {Average: Θ(n(logn)^2), Worse: O(n(logn)^2), Best: Ω(nlogn)}
Space complexity: {O(1)}
1 2 3 4 5 6 7 8 9 10 11
defshell_sort(list): gap = len(list) // 2 while gap > 0: for i in range(gap, len(list)): temp = list[i] j = i while j >= gap and list[j - gap] > temp: list[j], list[j - gap] = list[j - gap], temp j -= gap gap = gap // 2 return list
generating permutations
JohnsonTrotter
Time complexity: O(n!)
binary search 折半查找
Time complexity: {Average: Θ(logn), Worse: O(logn), Best: Ω(1)}
defquick_select_m(list, start, end, k_th_min): s = partition(list, start, end) if s == k_th_min - 1: return list[s] elif s > k_th_min - 1: return quick_select_m(list, start, s - 1, k_th_min) else: return quick_select_m(list, s + 1, end, k_th_min) defpartition(list, start, end): pivot = list[start] i = start + 1 j = end whileTrue: while list[i] <= pivot and i <= j: i += 1 while list[j] >= pivot and j >= i: j -= 1 if i > j: break list[i], list[j] = list[j], list[i] list[start], list[j] = list[j], list[start] return j
Divide-And-Conquer 分治法
分解问题,求解子问题,合并自问题的解 T(n) = aT(n/b) + f(n) {a个需要求解的问题,问题被分成b个,f(n)的分解合并时间消耗} T(n) = O(n^d) if a < b^d or O(n^dlogn) if a = b^d or O(n^log_b(a)) if a > b^d
merge sort 归并排序
{除了heapsort以外唯一BestAveWorst全是O(nlogn)排序算法}
两种实现方法(自顶向下-递归, 自底向上-循环)
Time complexity: {Average: Θ(nlogn), Worse: O(nlogn), Best: Ω(nlogn)}
defmerge_sort(list): if len(list) > 1: list_b = list[:len(list) // 2] list_c = list[len(list) // 2:] return merge(merge_sort(list_b), merge_sort(list_c)) else: return list defmerge(list_b, list_c): list_a = list_b + list_c #init list_a i, j, k = 0, 0, 0 while i < len(list_b) and j < len(list_c): if list_b[i] <= list_c[j]: list_a[k] = list_b[i] i += 1 else: list_a[k] = list_c[j] j += 1 k += 1 if i == len(list_b): for index in range(j, len(list_c)): list_a[k] = list_c[index] k += 1 if j == len(list_c): for index in range(i, len(list_b)): list_a[k] = list_b[index] k += 1 return list_a
quick sort 快速排序
{pivot的选择对于算法效率至关重要}
不断选择pivot来将元素划分到它的左右来实现
Time complexity: {Average: Θ(nlogn), Worse: O(n^2), Best: Ω(nlogn)}