標籤:次數 簡單 快速排序 python實現 需要 規範 已耗用時間 原理 限時
一、 演算法是什嗎?
演算法是指解題方案的準確而完整的描述,是一系列解決問題的清晰指令,演算法代表著用系統的方法描述解決問題的策略機制。也就是說,能夠對一定規範的輸入,在有限時間內獲得所要求的輸出。如果一個演算法有缺陷,或不適合於某個問題,執行這個演算法將不會解決這個問題。不同的演算法可能用不同的時間、空間或效率來完成同樣的任務。一個演算法的優劣可以用空間複雜度與時間複雜度來衡量。
二、 時間複雜度:
時間複雜度是用來估計演算法已耗用時間的一個式子(單位)
一般來說*,時間複雜度高的演算法比複雜度低的演算法慢
常見時間複雜度單位:效率從上到下變低,
O(1) 簡單的一次運算
O(logn) 迴圈減半
O(n) 一次迴圈
O(nlogn) 一個迴圈加一個迴圈減半
O(n^2) 兩個迴圈
O(n^2logn)
O(n^3)
如何一眼判斷時間複雜度?
迴圈減半的過程àO(logn)
幾次迴圈就是n的幾次方的複雜度
三、 空間複雜度
空間複雜度是用來評估演算法記憶體佔用大小的單位
空間換時間:如果需要增快演算法的速度,需要的空間會更大
四、python實現常見的演算法
1、冒泡(交換)排序
原理:列表中兩個相鄰的數,如果前一個數比後一個數大,就做交換。一共需要遍曆列表的次數是len(lst)-1
時間複雜度:O(n^2)
1 def bubble_sort(lst):2 for i in range(len(lst)-1): # 這是需要迴圈遍曆多少次3 for j in range(len(lst)-i-1): # 每次數組中的無序區4 if lst[j] >lst[j+1]:5 lst[j],lst[j+1] = lst[j+1],lst[j]6 7 lst = [1, 2, 44, 3, 5]8 bubble_sort(lst)9 print(lst)
最佳化:如果在迴圈的時候,有一次沒有進行交換,就表示數列中的資料已經是有序的
時間複雜度:最好情況是0(n),只遍曆一次,一般情況和最壞情況都是O(n^2)
1 def bubble_sort(lst): 2 for i in range(len(lst)-1): # 這是需要迴圈遍曆多少次 3 change = False # 做一個標誌變數 4 for j in range(len(lst)-i-1): # 每次數組中的無序區 5 if lst[j] >lst[j+1]: 6 lst[j],lst[j+1] = lst[j+1],lst[j] 7 change = True # 每次遍曆,如果進來排序的話,就會改變change的值 8 if not change: # 如果change沒有改變,那就表示當前的序列是有序的,直接跳出迴圈即可 9 return10 11 12 lst = [1, 2, 44, 3, 5]13 bubble_sort(lst)14 print(lst)
2、選擇排序
原理:每次遍曆找到當下數組最小的數,並把它放到第一個位置,下次遍曆剩下的無序區
1 def select_sort(lst): 2 for i in range(len(lst) - 1): # 當前需遍曆的次數 3 min_loc = i # 當前最小數的位置 4 for j in range(i+1, len(lst)): # 無序區 5 if lst[j] < lst[min_loc]: # 如果有更小的數 6 min_loc = j # 最小數的位置改變 7 if min_loc != i: 8 lst[i], lst[min_loc] = lst[min_loc], lst[i] # 把最小數和無序區第一個數交換交換 9 10 lst = [1, 2, 44, 3, 5]11 select_sort(lst)12 print(lst)
3、插入排序
原理:列表分為有序區和無序區,有序區是一個相對有序的序列,認為一開始的時候有序區有一值
每次從無序區選擇一個值,放到有序區,直到無序區為空白
1 def insert_sort(lst): 2 for i in range(1,len(lst)): # 從1開始遍曆表示無序區從1開始,有序區初始有一個值 3 tmp = lst[i] # tmp表示拿到的無序區的第一張牌 4 j = i - 1 # j表示有序區的最後一個值 5 while j >= 0 and lst[j] > tmp: # 當有序區有值,並且有序區的值比無序區拿到的值大就一直迴圈 6 lst[j+1] = lst[j] # 有序區的值往後移 7 j -= 1 # 找到上一個有序區的值,然後再迴圈 8 lst[j+1] = tmp # 跳出迴圈之後,只有j+1的位置是空的,要把當下無序區的值放到j+1的位置 9 10 lst = [1, 2, 44, 3, 5]11 insert_sort(lst)12 print(lst)
二分插入:實際上並沒有最佳化的效果
1 def insert_sort(lst): 2 for i in range(1, len(lst)): 3 left = 0 4 right = i - 1 5 tmp = lst[i] 6 while left <= right: 7 mid = (left + right) / 2 8 if tmp >= lst[mid]: 9 left = mid + 110 if tmp < lst[mid]:11 right = mid - 112 for j in range(i - 1, left - 1, -1): # [i-1,left]13 lst[j + 1] = lst[j]14 lst[left] = tmp15 16 return lst
4、快速排序
思路:取第一個元素,讓它歸位,就是放到一個位置,使它左邊的都比它小,右邊的都比它大,然後遞迴
先歸位,後遞迴
時間複雜度:O(nlog(n))
最壞情況:
最壞情況下的事件複雜度是O(n2)
標誌數的左邊或者右邊只有一個數
解決方案:不要找第一個元素,隨機找一個元素
1 def parttion(lst, left, right): 2 i = left 3 j = right 4 tmp = lst[i] # 把此次迴圈的標誌數存起來 5 while i < j: 6 while i < j and lst[j] > tmp: # 先從右邊開始找比標誌數小的,有的話跳出迴圈 7 j -= 1 8 lst[i] = lst[j] # 跳出迴圈之後,把這個比標誌數小的值放到標誌數的位置 9 while i < j and lst[i] < tmp: # 左邊的排序方法和右邊一樣10 i += 111 lst[j] = lst[i]12 lst[i] = tmp # 整個排序結束之後,把一開始的標誌數放回空位13 return i14 15 16 def quick_sort(lst, left, right):17 if left < right: # 至少有兩個元素18 p = parttion(lst, left, right)19 quick_sort(lst, left, p-1)20 quick_sort(lst, p+1, right)21 22 23 lst = [1, 2, 44, 3, 5]24 quick_sort(a, 0, 4)25 print(lst)
python實現常見演算法