Python十大經典排序算法


現在很多的事情都可以用算法來解決,在編程上,算法有着很重要的地位,將算法用函數封裝起來,使程序能更好的調用,不需要反復編寫。

Python十大經典算法:

 

一、插入排序

1.算法思想

從第二個元素開始和前面的元素進行比較,如果前面的元素比當前元素大,則將前面元素 后移,當前元素依次往前,直到找到比它小或等於它的元素插入在其后面,

然后選擇第三個元素,重復上述操作,進行插入,依次選擇到最后一個元素,插入后即完成所有排序。

2.代碼實現

 1 def insertion_sort(arr):
 2     #插入排序
 3     # 第一層for表示循環插入的遍數
 4     for i in range(1, len(arr)):
 5         # 設置當前需要插入的元素
 6         current = arr[i]
 7         # 與當前元素比較的比較元素
 8         pre_index = i - 1
 9         while pre_index >= 0 and arr[pre_index] > current:
10             # 當比較元素大於當前元素則把比較元素后移
11             arr[pre_index + 1] = arr[pre_index]
12             # 往前選擇下一個比較元素
13             pre_index -= 1
14         # 當比較元素小於當前元素,則將當前元素插入在 其后面
15         arr[pre_index + 1] = current
16     return arr

二、選擇排序

1.算法思想

設第一個元素為比較元素,依次和后面的元素比較,比較完所有元素找到最小的元素,將它和第一個元素互換,重復上述操作,我們找出第二小的元素和第二個位置的元素互換,以此類推找出剩余最小元素將它換到前面,即完成排序。

2.代碼實現

 1 def selection_sort(arr):
 2     #選擇排序
 3     # 第一層for表示循環選擇的遍數
 4     for i in range(len(arr) - 1):
 5         # 將起始元素設為最小元素
 6         min_index = i
 7         # 第二層for表示最小元素和后面的元素逐個比較
 8         for j in range(i + 1, len(arr)):
 9             if arr[j] < arr[min_index]:
10                 # 如果當前元素比最小元素小,則把當前元素角標記為最小元素角標
11                 min_index = j
12         # 查找一遍后將最小元素與起始元素互換
13         arr[min_index], arr[i] = arr[i], arr[min_index]
14     return arr

 

三、冒泡排序

1.算法思想

從第一個和第二個開始比較,如果第一個比第二個大,則交換位置,然后比較第二個和第三個,逐漸往后,經過第一輪后最大的元素已經排在最后,

所以重復上述操作的話第二大的則會排在倒數第二的位置。,那重復上述操作n-1次即可完成排序,因為最后一次只有一個元素所以不需要比較。

2.代碼實現

 1 def bubble_sort(arr):
 2     #冒泡排序
 3     # 第一層for表示循環的遍數
 4     for i in range(len(arr) - 1):
 5         # 第二層for表示具體比較哪兩個元素
 6         for j in range(len(arr) - 1 - i):
 7             if arr[j] > arr[j + 1]:
 8                 # 如果前面的大於后面的,則交換這兩個元素的位置
 9                 arr[j], arr[j + 1] = arr[j + 1], arr[j]
10     return arr

 

四、快速排序

1.算法思想

找出基線條件,這種條件必須盡可能簡單,不斷將問題分解(或者說縮小規模),直到符合基線條件。

2.代碼實現

 1 def quick_sort(arr):
 2   if len(arr) < 2:
 3     # 基線條件:為空或只包含一個元素的數組是“有序”的
 4     return arr
 5   else:
 6     # 遞歸條件
 7     pivot = arr[0]
 8     # 由所有小於基准值的元素組成的子數組
 9     less = [i for i in arr[1:] if i <= pivot]
10     # 由所有大於基准值的元素組成的子數組
11     greater = [i for i in array[1:] if i > pivot]
12     return quicksort(less) + [pivot] + quicksort(greater)
13 
14 print(quick_sort([10, 5, 2, 3]))

 

五、歸並排序

1.算法思想

歸並排序是分治法的典型應用。分治法(Divide-and-Conquer):將原問題划分成 n 個規模較小而結構與原問題相似的子問題;遞歸地解決這些問題,然后再合並其結果,就得到原問題的解,分解后的數列很像一個二叉樹。

具體實現步驟:

  1. 使用遞歸將源數列使用二分法分成多個子列

  2. 申請空間將兩個子列排序合並然后返回

  3. 將所有子列一步一步合並最后完成排序

  4. 注:先分解再歸並

2.代碼實現

 1 def merge_sort(arr):
 2     #歸並排序
 3     if len(arr) == 1:
 4         return arr
 5     # 使用二分法將數列分兩個
 6     mid = len(arr) // 2
 7     left = arr[:mid]
 8     right = arr[mid:]
 9     # 使用遞歸運算
10     return marge(merge_sort(left), merge_sort(right))
11 
12 
13 def marge(left, right):
14     #排序合並兩個數列
15     result = []
16     # 兩個數列都有值
17     while len(left) > 0 and len(right) > 0:
18         # 左右兩個數列第一個最小放前面
19         if left[0] <= right[0]:
20             result.append(left.pop(0))
21         else:
22             result.append(right.pop(0))
23     # 只有一個數列中還有值,直接添加
24     result += left
25     result += right
26     return result

六、希爾排序

1.算法思想

希爾排序的整體思想是將固定間隔的幾個元素之間排序,然后再縮小這個間隔。這樣到最后數列就成為了基本有序數列。

具體步驟:

  1. 計算一個增量(間隔)值

  2. 對元素進行增量元素進行比較,比如增量值為7,那么就對0,7,14,21…個元素進行插入排序

  3. 然后對1,8,15…進行排序,依次遞增進行排序

  4. 所有元素排序完后,縮小增量比如為3,然后又重復上述第2,3步

  5. 最后縮小增量至1時,數列已經基本有序,最后一遍普通插入即可

2.代碼實現

 1 def shell_sort(arr):
 2     #希爾排序
 3     # 取整計算增量(間隔)值
 4     gap = len(arr) // 2
 5     while gap > 0:
 6         # 從增量值開始遍歷比較
 7         for i in range(gap, len(arr)):
 8             j = i
 9             current = arr[i]
10             # 元素與他同列的前面的每個元素比較,如果比前面的小則互換
11             while j - gap >= 0 and current < arr[j - gap]:
12                 arr[j] = arr[j - gap]
13                 j -= gap
14             arr[j] = current
15         # 縮小增量(間隔)值
16         gap //= 2
17     return arr

七、基數排序

1.算法思想

基數排序(radix sort)屬於“分配式排序”(distribution sort),又稱“桶子法”(bucket sort)或bin sort,顧名思義,它是透過鍵值的部份資訊,將要排序的元素分配至某些“桶”中,藉以達到排序的作用,基數排序法是屬於穩定性的排序,其時間復雜度為O (nlog(r)m),其中r為所采取的基數,而m為堆數,在某些時候,基數排序法的效率高於其它的穩定性排序法。

2.代碼實現

2.1由桶排序改造,從最低位到最高位依次桶排序,最后輸出最后排好的列表。

 1 def RadixSort(list,d):
 2     for k in range(d):#d輪排序
 3         # 每一輪生成10個列表
 4         s=[[] for i in range(10)]#因為每一位數字都是0~9,故建立10個桶
 5         for i in list:
 6             # 按第k位放入到桶中
 7             s[i//(10**k)%10].append(i)
 8         # 按當前桶的順序重排列表
 9         list=[j for i in s for j in i]
10     return list

2.2簡單實現

 1 from random import randint
 2 def radix_sort():
 3   A = [randint(1, 99999999) for _ in xrange(9999)]
 4   for k in xrange(8):
 5     S = [ [] for _ in xrange(10)]
 6     for j in A:
 7       S[j / (10 ** k) % 10].append(j)
 8     A = [a for b in S for a in b]
 9   for i in A:
10     print i

八、計數排序

1.算法思想

對每一個輸入元素x,確定小於x的元素個數。利用這一信息,就可以直接把x 放在它在輸出數組上的位置上了,運行時間為O(n),但其需要的空間不一定,空間浪費大。

2.代碼實現

 1 from numpy.random import randint
 2 def Conuting_Sort(A):
 3     k = max(A)          # A的最大值,用於確定C的長度
 4     C = [0]*(k+1)       # 通過下表索引,臨時存放A的數據
 5     B = (len(A))*[0]    # 存放A排序完成后的數組
 6     for i in range(0, len(A)):
 7         C[A[i]] += 1    # 記錄A有哪些數字,值為A[i]的共有幾個
 8     for i in range(1, k+1):
 9         C[i] += C[i-1]  # A中小於i的數字個數為C[i]
10     for i in range(len(A)-1, -1, -1):
11         B[C[A[i]]-1] = A[i] # C[A[i]]的值即為A[i]的值在A中的次序
12         C[A[i]] -= 1    # 每插入一個A[i],則C[A[i]]減一
13     return B

九、堆排序

1.算法思想

堆分為最大堆和最小堆,是完全二叉樹。堆排序就是把堆頂的最大數取出,將剩余的堆繼續調整為最大堆,具體過程在第二塊有介紹,以遞歸實現 ,

剩余部分調整為最大堆后,再次將堆頂的最大數取出,再將剩余部分調整為最大堆,這個過程持續到剩余數只有一個時結束。

2.代碼實現

 1 import time,random
 2 def sift_down(arr, node, end):
 3     root = node
 4     #print(root,2*root+1,end)
 5     while True:
 6         # 從root開始對最大堆調整
 7         child = 2 * root +1  #left child
 8         if child  > end:
 9             #print('break',)
10             break
11         print("v:",root,arr[root],child,arr[child])
12         print(arr)
13         # 找出兩個child中交大的一個
14         if child + 1 <= end and arr[child] < arr[child + 1]: #如果左邊小於右邊
15             child += 1 #設置右邊為大
16         if arr[root] < arr[child]:
17             # 最大堆小於較大的child, 交換順序
18             tmp = arr[root]
19             arr[root] = arr[child]
20             arr[child]= tmp
21             # 正在調整的節點設置為root
22             #print("less1:", arr[root],arr[child],root,child)
23             root = child #
24             #[3, 4, 7, 8, 9, 11, 13, 15, 16, 21, 22, 29]
25             #print("less2:", arr[root],arr[child],root,child)
26         else:
27             # 無需調整的時候, 退出
28             break
29     #print(arr)
30     print('-------------')
31  
32 def heap_sort(arr):
33     # 從最后一個有子節點的孩子還是調整最大堆
34     first = len(arr) // 2 -1
35     for i in range(first, -1, -1):
36         sift_down(arr, i, len(arr) - 1)
37     #[29, 22, 16, 9, 15, 21, 3, 13, 8, 7, 4, 11]
38     print('--------end---',arr)
39     # 將最大的放到堆的最后一個, 堆-1, 繼續調整排序
40     for end in range(len(arr) -1, 0, -1):
41         arr[0], arr[end] = arr[end], arr[0]
42         sift_down(arr, 0, end - 1)
43         #print(arr)

十、桶排序

1.算法思想

為了節省空間和時間,我們需要指定要排序的數據中最小以及最大的數字的值,來方便桶排序算法的運算。

2.代碼實現

 1 #桶排序
 2 def bucket_sort(the_list):
 3     #設置全為0的數組
 4     all_list = [0 for i in range(100)]
 5     last_list = []
 6     for v in the_list:
 7         all_list[v] = 1 if all_list[v]==0 else all_list[v]+1
 8     for i,t_v in enumerate(all_list):
 9         if t_v != 0:
10             for j in range(t_v):
11                 last_list.append(i)
12     return last_list

 總結:

在編程中,算法都是相通的,算法重在算法思想,相當於將一道數學上的應用題的每個條件,區間,可能出現的結果進行分解,分步驟的實現它。算法就是將具體問題的共性抽象出來,將步驟用編程語言來實現。通過這次對排序算法的整理,加深了對各算法的了解,具體的代碼是無法記憶的,通過對算法思想的理解,根據偽代碼來實現具體算法的編程,才是真正了解算法。


免責聲明!

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



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