算法目錄
-
二分查找
-
大O表示法
-
選擇排序
-
遞歸
-
快速排序,分而治之(D&C)
-
散列表——字典
-
廣度優先搜索——BFS
-
Dijkstra算法
-
貪婪算法
二分查找

1 # 要求list是有序表,num是要查找的數字 2 # 二分查找貌似只能查找數值表 3 def binary_search(list, num): 4 low = 0 5 high = len(list) - 1 # 因為python數組(列表)是從0開始索引的 6 7 while low <= high: 8 mid = (low + high) 9 guess = list[mid] 10 if guess == num: 11 return "found it is " + str(mid) 12 if guess > num: 13 high = mid - 1 14 else: 15 low = mid + 1 16 return "not found" 17 18 # python數組不同於matlab數組,python中間要用逗號隔開,而matlab不用 19 my_list = [1, 3, 5, 7, 9, 11, 13] 20 print(binary_search(my_list, 6)) 21 print(binary_search(my_list, 9))
大O表示法
1. 能夠比較操作數,表示算法運行時間的增速
2. 給出了一個時間的上限
3. 算法的速度並非時間,而是操作數的增速
4. O(logn)——對數時間(二分查找)
5. O(n)——線性時間(順序查找)
6. O(n*logn)——快速排序
7. O(n^2)——選擇排序
8. O(n!)——旅行商問題的解決辦法
9. 常量並不會影響到大O表示法
選擇排序
* 計算機內存如同一大堆抽屜
* 需要存儲多個元素時可采用鏈表或數組
* 數組元素都在一起,因此讀取速度快
* 鏈表是分開的,但是插入和刪除速度很快
* 鏈表數組查找比數組慢,比鏈表快;插入比數組快,與鏈表相當
* 同一數組元素的類型均相同

1 尋找數組中的最小值的索引 2 def find_smallest_index(arr): 3 smallest = arr[0] 4 smallest_index = 0; 5 # python中檢查數組長度的函數是len,而matlab中是length 6 for i in range(1, len(arr)): 7 if arr[i] < smallest: 8 smallest = arr[i] 9 smallest_index = i 10 return smallest_index 11 12 # 對數組進行排序 13 def selection_insort(arr): 14 # create new array 15 new_arr = [] 16 for i in range(len(arr)): 17 smallest_index = find_smallest_index(arr) 18 # array.pop()只能根據索引值彈出元素,so pop()應傳入索引值 19 new_arr.append(arr.pop(smallest_index)) 20 return new_arr 21 22 mess_arr = [3, 1, 9, 2, 5, 4] 23 print("This is uninsort array: " + str(mess_arr)) 24 insorted_arr = selection_insort(mess_arr) 25 print("This is insorted array: " + str(insorted_arr))
遞歸
* 使用循環程序性能可能更高,使用遞歸程序可能更容易理解
* 遞歸條件——讓函數調用自己;基線條件——讓函數不再調用自己
* 所有函數調用都進入遞歸調用棧

1 # 一個計算數學階乘的遞歸調用 2 def func(x): 3 if x == 1: 4 return 1 5 else: 6 return x * func(x-1) 7 8 print(func(3)) 9 10 11 #一個計算數組和的遞歸調用 12 def func(arr): 13 if arr == []: 14 return 0 15 else: 16 # 這里不能用arr[0] + func()因為基線條件是arr==[]當arr 17 # 只有一個元素時python會將arr變為一個int數值,而不會是數組 18 return arr.pop() + func(arr) 19 20 arr = [2, 3, 4] 21 print(func(arr))
快速排序,分而治之(D&C)
* 找出基線條件(很可能是一個空數組或者只包含一個元素的數組)
* 不斷將問題分解直至滿足基線條件
* 快速排序:
* 選取基准值
* 將數組分為兩個子數組:小於基准值的元素和大於基准值的元素
* 對這兩個子數組進行快速排序
View Code
View Code
View Code

1 # 快速排序——by myself 2 def quickly_sort(arr): 3 # 兩個基線條件 4 if len(arr) < 2: 5 return arr 6 # 直接選取數組元素第一個當作基准值——遞歸條件 7 reference_value = arr[0] 8 larger_arr = [] 9 smaller_arr = [] 10 for i in range(1,len(arr)): 11 if arr[i] > reference_value: 12 larger_arr.append(arr[i]) 13 # arr.pop(i) 14 else: 15 smaller_arr.append(arr[i]) 16 # arr.pop(i) 17 return quickly_sort(smaller_arr) + [reference_value] + quickly_sort(larger_arr) 18 19 mess_arr = [3, 1, 9, 2, 5, 4] 20 print("This is uninsort array: " + str(mess_arr)) 21 insorted_arr = quickly_sort(mess_arr) 22 print("This is insorted array: " + str(insorted_arr))

1 # 快速排序——by others 2 def quickly_sort(arr): 3 # 基線條件 4 if len(arr) < 2: 5 return arr 6 else: 7 # 選取基准值——遞歸條件 8 pivot = arr[0] 9 10 # 簡潔明了選出較大數組與較小數組 11 larger = [i for i in arr[1:] if i > pivot] 12 smaller = [i for i in arr[1:] if i <= pivot] 13 # 遞歸調用 14 return quickly_sort(smaller) + [pivot] + quickly_sort(larger) 15 16 mess_arr = [3, 1, 9, 2, 5, 4] 17 print("This is uninsort array: " + str(mess_arr)) 18 insorted_arr = quickly_sort(mess_arr) 19 print("This is insorted array: " + str(insorted_arr))
散列表——字典
* 散列函數——將輸入映射到數字;同一輸入映射一致,不同輸入映射到不同的數字
* 良好散列表包括:較低的填裝因子0.7以下,良好的散列函數SHA函數
* 散列表查找(O(1))、刪除、插入都非常快
* 散列表適用於模擬映射關系、防止重復以及緩存數據

1 # 散列表——字典 2 # 創建字典的兩種方案 3 price_list = dict() 4 price_list = {} 5 6 7 # 添加數據 8 price_list["apple"] = 0.67 9 price_list["milk"] = 1.49 10 price_list["bread"] = 0.49 11 12 print(price_list) 13 print(price_list.keys()) 14 print(price_list.values()) 15 print(price_list.items()) 16 17 # 判斷是否在散列表中 18 flag = price_list.get("apple") 19 print(flag) 20 # 不同大小寫詩不同與阿奴 21 flag = price_list.get("Apple") 22 print(flag) 23 flag = price_list.get("banana") 24 print(flag)
廣度優先搜索——BFS
* 用於解決最短路徑
* 利用import collection import deque 創建一個雙端隊列
* 棧是LIFO,隊列是FIFO
* 廣度優先搜索時,對於檢查過的人不能再去檢查

1 # 廣度優先搜索示例 2 from collections import deque 3 4 # 創建一個關系圖(散列表) 5 graph = {} 6 # 單引號與雙引號基本無使用上的區別,但是三引號可實現跨行輸出 7 graph["you"] = ["alice", 'bob', "claire"] 8 graph["alice"] = ['peggy'] 9 graph["bob"] = ["anuj", 'peggy'] 10 graph['claire'] = ["thom", 'jonny'] 11 graph["peggy"] = [] 12 graph["anuj"] = [] 13 graph["thom"] = [] 14 graph["jonny"] = [] 15 16 17 search_queue = deque() 18 search_queue += graph["you"] 19 20 # 判斷是否為經銷商 21 def person_is_seller(name): 22 return (name[-1] == 'o') 23 24 def search(search_queue): 25 searched = [] 26 while search_queue: 27 28 person = search_queue.popleft() #取出隊列左邊第一個元素 29 # 檢查后不再檢查 30 if person not in searched: 31 if person_is_seller(person): 32 print(person + " is a mago seller !") 33 return True 34 else: 35 # 把TA的朋友加入搜索隊列 36 search_queue += graph[person] 37 searched.append(person) 38 print("Can't find mago seller in your friends") 39 return False 40 search(search_queue)
Dijkstra算法
* 找出目前最便宜的節點
* 更新該節點的鄰居的開銷
* 重復這個過程,直到對圖中所有節點都這么做了
* 計算最終路徑
* Dijkstra算法只適用與有向無環圖
* 對於包含負權邊的圖,請使用貝爾曼-福德算法graph

1 # Dijkstra算法 2 3 # 尋找lowest_cost_node 4 def find_lowest_cost_node(costs): 5 lowest_cost = float("inf") 6 lowest_cost_node = None 7 for node in costs: 8 cost = costs[node] 9 if cost < lowest_cost and node not in processed: 10 lowest_cost = cost 11 lowest_cost_node = node 12 return lowest_cost_node 13 14 15 # Create a graph 16 graph = {} 17 graph['start'] = {} 18 graph['start']['a'] = 6 19 graph['start']['b'] = 2 20 graph['a'] = {} 21 graph['a']['fin'] = 1 22 graph['b'] = {} 23 graph['b']['fin'] = 5 24 graph['b']['a'] = 3 25 graph['fin'] = {} 26 27 28 # create a cost dict 29 infinity = float('inf') 30 costs = {} 31 costs['a'] = 6 32 costs['b'] = 2 33 costs['fin'] = infinity 34 35 # creata a parent dict 36 parents = {} 37 parents['a'] = "start" 38 parents['b'] = "start" 39 parents['fin'] = None 40 41 42 # record processed nodes 43 processed = [] 44 45 46 node = find_lowest_cost_node(costs) 47 while node is not None: 48 cost = costs[node] 49 neighbors = graph[node] 50 for n in neighbors.keys(): 51 new_cost = cost + neighbors[n] 52 if costs[n] > new_cost: 53 costs[n] = new_cost 54 parents[n] = node 55 processed.append(node) 56 node = find_lowest_cost_node(costs) 57 58 route = ['fin'] 59 node = parents['fin'] 60 route.append(node) 61 node = parents[node] 62 route.append(node) 63 node = parents[node] 64 route.append(node) 65 66 67 print(route)
貪婪算法
* 衡量標准:速度有多快;得到的近似解與最優解的接近程度
* 易於實現,運行速度快
* 識別NP完全問題
* 隨着元素的增加操作速度極速增加
* 涉及“所有組合”的問題通常是NP完全問題
* 問題可轉換為集合覆蓋問題和旅行商問題