十大經典排序算法的python實現


十種常見排序算法可以分為兩大類

  非線性時間比較類排序:通過比較來決定元素間的相對次序,由於其時間復雜度不能突破O(nlogn),因此稱為非線性時間比較類排序。包括:冒泡排序、選擇排序、歸並排序、快速排序、插入排序、希爾排序、堆排序等。

  線性時間非比較類排序:不通過比較來決定元素間的相對次序,它可以突破基於比較排序的時間下界,以線性時間運行,因此稱為線性時間非比較類排序。包括:計數排序、桶排序、基數排序等。

下面介紹各種算法的基本思想及python實現:

1  冒泡排序(Bubble Sort)

1.1 基本思想:

  它重復地走訪過要排序的數列,一次比較兩個元素,如果它們的順序錯誤就把它們交換過來。走訪數列的工作是重復地進行直到沒有再需要交換,也就是說該數列已經排序完成。

 

1.2 實現代碼:

1 def bubbleSort(arr):
2     n = len(arr)
3     for i in range(n-1):
4         for j in range(n-i-1):
5             if arr[j] > arr[j+1]:
6                 arr[j], arr[j+1] = arr[j+1], arr[j]
7     return arr

 

2  選擇排序(Selection Sort)

2.1 基本思想:

  首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再從剩余未排序元素中繼續尋找最小(大)元素,然后放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。

 

2.2 實現代碼

1 def selectionSort(arr):
2     n = len(arr)
3     for i in range(n-1):
4         minIndex = i
5         for j in range(i+1, n, 1):
6             if arr[j] < arr[minIndex]:
7                 minIndex = j
8         arr[i], arr[minIndex] = arr[minIndex], arr[i]
9     return arr

 

3 插入排序(Insertion Sort)

3.1 基本思想

  通過構建有序序列,對於未排序數據,在已排序序列中從后向前掃描,找到相應位置並插入。

 

3.2 實現代碼

1 def insertionSort(arr):
2     n = len(arr)
3     for i in range(1, n):
4         for j in range(i, 0, -1):
5             if arr[j] < arr[j-1]:
6                 arr[j-1], arr[j] = arr[j], arr[j-1]
7     return arr

 

4  希爾排序(Shell Sort)

4.1 基本思想

  它是簡單插入排序的改進版。它與插入排序的不同之處在於,它會優先比較距離較遠的元素,將整個待排序的記錄序列分割成為若干子序列分別進行直接插入排序。希爾排序又叫縮小增量排序

 

4.2 實現代碼

 1 def shellsort(arr):
 2     n = len(arr)
 3     group = 3
 4     gap = n // group
 5     while gap > 0:
 6         for i in range(0, gap):
 7             for j in range(i+gap, n, gap):
 8                 tmp = arr[j]
 9                 for k in range(j-gap, i-1, -gap):
10                     if arr[k] >= arr[j]:
11                         arr[k + gap], arr[k] = arr[k], tmp
12         gap //= group
13     return arr

 

5 歸並排序(Merge Sort)

5.1 基本思想

  歸並排序是建立在歸並操作上的一種有效的排序算法。該算法是采用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合並,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合並成一個有序表,稱為2-路歸並。 

 

5.2 實現代碼

 1 def mergeSort(arr):
 2     if len(arr) < 2:
 3         return arr
 4     middle = int(len(arr) / 2)
 5     left = mergeSort(arr[:middle])
 6     right = mergeSort(arr[middle:])
 7     return merge(left, right)
 8 def merge(left, right):
 9     result = []
10     leftindex = rightindex = 0
11     while leftindex < len(left) and rightindex < len(right):
12         if left[leftindex] <= right[rightindex]:
13             result.append(left[leftindex])
14             leftindex += 1
15         else:
16             result.append(right[rightindex])
17             rightindex += 1
18     if len(left):
19         for i in left[leftindex:]:
20             result.append(i)
21     if len(right):
22         for i in right[rightindex:]:
23             result.append(i)
24     return result

 

6  快速排序(Quick Sort)

6.1 基本思想

  通過一趟排序將待排記錄分隔成獨立的兩部分,其中一部分記錄的關鍵字均比另一部分的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序。

 

6.2 實現代碼

 1 def quickSort(arr, left, right):
 2     if left < right:
 3         partitionIndex = partition(arr, left, right)
 4         quickSort(arr, left, partitionIndex - 1)
 5         quickSort(arr, partitionIndex + 1, right)
 6         return arr
 7 def partition(arr, left ,right):
 8     pivot = right
 9     i = left - 1
10     for j in range(left, right):
11         if arr[j] <= arr[pivot]:
12             i += 1
13             arr[i], arr[j] = arr[j], arr[i]
14     arr[i+1], arr[pivot] = arr[pivot], arr[i+1]
15     # print(arr)
16     return i + 1

 

7  堆排序(Heap Sort)

7.1 基本思想

  堆排序(Heapsort)是指利用堆這種數據結構所設計的一種排序算法。堆積是一個近似完全二叉樹的結構,並同時滿足堆積的性質:即子結點的鍵值或索引總是小於(或者大於)它的父節點。

 

7.2 代碼實現

 1 def adjust_heap(arr, i, n):
 2     lchild = 2 * i + 1
 3     rchild = 2 * i + 2
 4     max = i
 5     if i < n / 2:
 6         if lchild < n and arr[lchild] > arr[max]:
 7             max = lchild
 8         if rchild < n and arr[rchild] > arr[max]:
 9             max = rchild
10         if max != i:
11             arr[max], arr[i] = arr[i], arr[max]
12             adjust_heap(arr, max, n)              # 下濾
13 def build_max_heap(arr, n):
14     for i in range(0, int(n // 2))[::-1]:
15         adjust_heap(arr, i, n)
16 def heap_sort(arr):
17     n = len(arr)
18     build_max_heap(arr, n)
19     for i in range(0, n)[::-1]:
20         arr[0], arr[i] = arr[i], arr[0]
21         adjust_heap(arr, 0, i)                    # 下濾
22     return arr

 

8 計數排序

8.1 基本思想

  計數排序不是基於比較的排序算法,其核心在於將輸入的數據值轉化為鍵存儲在額外開辟的數組空間中。 作為一種線性時間復雜度的排序,計數排序要求輸入的數據必須是有確定范圍的整數。

 

8.2 實現代碼

 1 def countingSort(arr, maxValue):
 2     bucket = np.array(np.zeros(maxValue + 1))   # 算上0,arr必須是正數
 3     sortedIndex = 0
 4     bucketLen = maxValue + 1
 5     n = len(arr)
 6     for i in range(0, n):
 7         # if bucket[arr[i]]:
 8         bucket[arr[i]] += 1
 9     for j in range(0, bucketLen):
10         while bucket[j] > 0:
11             arr[sortedIndex] = j
12             sortedIndex += 1
13             bucket[j] -= 1
14     return arr

 

9 桶排序

9.1 基本思想

  假設輸入數據服從均勻分布,將數據分到有限數量的桶里,每個桶再分別排序(可以使用別的排序算法或是以遞歸方式繼續使用桶排序進行排)。

 

9.2 實現代碼

 1 def bucketSort(arr, bucketSize):
 2     if len(arr) == 0:
 3         return arr
 4     minValue = min(arr)           # 輸入數據的最小值
 5     maxValue = max(arr)           # 輸入數據的最大值
 6     # 桶的初始化
 7     DEFAULT_BUCKET_SIZE = 5      # 設置桶的默認數量為5
 8     bucketSize = bucketSize | DEFAULT_BUCKET_SIZE      # 按照位或(二進制)
 9     bucketCount = math.floor((maxValue - minValue) / bucketSize) + 1
10     buckets = [[] for i in range(bucketCount)]
11 
12     #  利用映射函數將數據分配到各個桶中
13     for i in range(0, len(arr)):
14         (buckets[math.floor((arr[i] - minValue) / bucketSize)]).append(arr[i])
15     arr = []
16     for i in range(0, len(buckets)):
17         insertionSort(buckets[i])               # 對每個桶進行排序,這里使用了插入排序
18         for j in range(0, len(buckets[i])):
19             arr.append(buckets[i][j])
20     return arr

 

10 基數排序

10.1 基本思想

  基數排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次類推,直到最高位。有時候有些屬性是有優先級順序的,先按低優先級排序,再按高優先級排序。最后的次序就是高優先級高的在前,高優先級相同的低優先級高的在前。

 

10.2 實現代碼

 1 import math
 2 def radix_sort(arr, radix=10):
 3     k = int(math.ceil(math.log(max(arr), radix)))   # 取得位數
 4     bucket = [[] for i in range(radix)]             # 初始化 bucket = [[],[],...]
 5     for i in range(1, k+1):
 6         for j in arr:
 7             bucket[j % (radix ** i) // (radix ** (i - 1))].append(j)   # 先截取元素的后k位數再取第k位上的數字(k=1,2...)
 8         del arr[:]
 9         for z in bucket:
10             arr += z
11             print(arr)
12             del z[:]
13     return arr

 

 

參考:https://www.cnblogs.com/onepixel/articles/7674659.html


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com