Python算法——《算法圖解》筆記


算法目錄 

  • 二分查找

  •  大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))
View Code

 大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))
View Code

遞歸

*   使用循環程序性能可能更高,使用遞歸程序可能更容易理解
*   遞歸條件——讓函數調用自己;基線條件——讓函數不再調用自己
*   所有函數調用都進入遞歸調用棧
 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))
View Code

快速排序,分而治之(D&C)

*   找出基線條件(很可能是一個空數組或者只包含一個元素的數組)
*   不斷將問題分解直至滿足基線條件
*   快速排序:
    *   選取基准值
    *   將數組分為兩個子數組:小於基准值的元素和大於基准值的元素
    *   對這兩個子數組進行快速排序
 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))
View Code
 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))
View Code

 散列表——字典

*   散列函數——將輸入映射到數字;同一輸入映射一致,不同輸入映射到不同的數字
*   良好散列表包括:較低的填裝因子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)
View Code

 廣度優先搜索——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)
View Code

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)
View Code

貪婪算法

*   衡量標准:速度有多快;得到的近似解與最優解的接近程度
*   易於實現,運行速度快
*   識別NP完全問題
    *   隨着元素的增加操作速度極速增加
    *   涉及“所有組合”的問題通常是NP完全問題
    *   問題可轉換為集合覆蓋問題和旅行商問題


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM