python拓展3 算法與數據結構
知識內容:
1.遞歸復習
2.常用算法
3.常用數據結構
4.python cookbook算法與數據結構整理
參考資料:
http://python3-cookbook.readthedocs.io/zh_CN/latest/index.html
http://www.cnblogs.com/alex3714/articles/5474411.html
一、遞歸復習
1.什麽是遞歸:函數內部自己調用自己
2.遞歸的特點
- 必須有一個明確的結束條件
- 每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減少
- 遞歸效率不高,遞歸層次過多會導致棧溢出
3.看函數說結果
1 def func1(x):2 print(x) 3 func1(x-1) 4 func1(5) 5 # 一直打印到限制次數(無出口) 6 7 def func2(x): 8 if x > 0: 9 print(x) 10 func2(x+1) 11 func2(5) 12 # 一直打印到限制次數(無出口) 13 14 def func3(x): 15 if x > 0: 16 print(x) 17 func3(x-1) 18 func3(5) 19 # 從5打印到1 20 21 def func4(x):22 if x > 0: 23 func4(x-1) 24 print(x) 25 func4(5) 26 # 從1打印到5
4.經典遞歸
(1)漢諾塔問題
解決思路:
假設有n個盤子:
- 1.把n-1個圓盤從A經過C移動到B
- 2.把第n個圓盤從A移動到C
- 3.把n-1個小圓盤從B經過A移動到C
1:
2:
3:
代碼:
1 def hanoi(a, b, c, n): 2 if n == 1: 3 print(a, "->", c) # 將n-1個盤子從a經過c移動到b 4 else: 5 hanoi(a, c, b, n-1) # 將剩余的最後一個盤子從a移動到c 6 print(a, "->", c) 7 hanoi(b, a, c, n-1) # 將n-1個盤子從b經過a移動到c 8 9 10 hanoi(‘柱子a‘, ‘柱子b‘, ‘柱子c‘, 4)
總結:漢諾塔移動次數的遞推式:h(x)=2h(x-1)+1
(2)字符串逆序輸出
1 def rvs(s): 2 if s == "": 3 return s 4 else: 5 return rvs(s[1:]) + s[0] 6 7 8 s = rvs("Hello, Python") 9 print(s)
5.尾遞歸
二、常用算法
1.什麽是算法
算法就是一個計算過程,解決問題的方法
算法(Algorithm)是指解題方案的準確而完整的描述,是一系列解決問題的清晰指令,算法代表著用系統的方法描述解決問題的策略機制。也就是說,能夠對一定規範的輸入,在有限時間內獲得所要求的輸出。如果一個算法有缺陷,或不適合於某個問題,執行這個算法將不會解決這個問題。不同的算法可能用不同的時間、空間或效率來完成同樣的任務。一個算法的優劣可以用空間復雜度與時間復雜度來衡量
一個算法應該具有以下七個重要的特征:
- 有窮性(Finiteness):算法的有窮性是指算法必須能在執行有限個步驟之後終止
- 確切性(Definiteness):算法的每一步驟必須有確切的定義
- 輸入項(Input):一個算法有0個或多個輸入,以刻畫運算對象的初始情況,所謂0個輸 入是指算法本身定出了初始條件
- 輸出項(Output):一個算法有一個或多個輸出,以反映對輸入數據加工後的結果。沒 有輸出的算法是毫無意義的
- 可行性(Effectiveness):算法中執行的任何計算步驟都是可以被分解為基本的可執行 的操作步,即每個計算步都可以在有限時間內完成(也稱之為有效性)
- 高效性(High efficiency):執行速度快,占用資源少
- 健壯性(Robustness):對數據響應正確
2.時間復雜度及空間復雜度
(1)時間復雜度
1 print("hello, world") 2 3 for i in range(n): 4 print("hello, world") 5 6 for i in range(n): 7 for j in range(n): 8 print("hello, world") 9 10 for i in range(n): 11 for j in range(n): 12 for k in range(n): 13 print("hello, world")
問以上代碼的運行時間誰最短?用什麽方法來提現代碼(算法)的運行快慢呢?答案就是用時間復雜度來衡量
常見算法的時間復雜度(由小到大排列):O(1) O(logn) O(n) O(nlogn) O(n^2) O(n^2logn) O(n^3)
實例:
1 print(‘hello world‘) 2 print(‘hello python‘) # O(1) 大O,可以認為它的含義是“order of”(大約是) 3 4 n= 64 5 while n>1: 6 print(n) # O(logn) # n=64是輸出依次為: 64 32 16 8 4 2 7 n = n//2 8 9 for i in range(n): 10 print(i) # O(n) 11 12 for i in range(n): 13 for j in range(n): 14 print(‘hello world‘) # O(n^2) 15 16 for i in range(n): 17 for j in range(n): 18 for k in range(n): 19 print(‘hello world‘) # O(n^3)
註:切片的復雜度是O(n) ,因為切的時候是賦值
總結:
- 時間復雜度是用來估計算法運行時間的一個式子(單位)
- 一般來說,時間復雜度高的算法比算法時間復雜度低的算法慢
- 循環減半的過程就是O(logn),幾次循環就是n的幾次方的復雜度
(2)空間復雜度
空間復雜度是用來評估算法內存占用大小的一個式子,常見的空間復雜度:O(1) O(n) O(n^2)
空間換時間:計算機的資源很充足,可以用空間的消耗來換取一定的時間
3.常用查找
(1)列表查找
列表查找:從列表中查找指定元素
輸入:列表、待查找的元素,輸出:元素下標或未查找到元素
列表查找的方法:順序查找和二分查找
- 順序查找:從列表第一個元素開始,順序進行搜索直到找到為止
- 二分查找:從有序列表的後續區開始查找,通過對查找的值和候選區中間的值進行比較,使候選區減半
以上兩種查找的代碼如下:
# 順序查找 時間復雜 O(n) def linear_search(find, data_list): for i in range(len(data_list)): if data_list[i] == find: return i return -1 # 二分查找 時間復雜 O(logn) def binary_search(find, data_list): low = 0 high = len(data_list) while low <= high: mid = (low + high) // 2 # 找到find if data_list[mid] == find: return mid # find在左半邊 elif data_list[mid] > find: high = mid - 1 # find在右半邊 else: low = mid + 1 # 未找到find返回-1 return -1
(2)查找練習
現在有一個學員信息列表(按id增序排列),格式為:
1 [ 2 {"id": 1001, "name": "張三", "age": 20}, 3 {"id": 1002, "name": "woz", "age": 22}, 4 {"id": 1003, "name": "alex", "age": 23}, 5 {"id": 1004, "name": "hf", "age": 26}, 6 {"id": 1005, "name": "kk", "age": 27}, 7 ]
現在要求修改二分查找代碼,輸入學生id,輸出該學生在該列表下的下標並輸出完整的學生信息
實現代碼如下:
4.常用排序
常用的排序有以下幾種:
三、常用數據結構
四、python cookbook算法與數據結構整理
python拓展3 算法與數據結構