前言:算法中排序也是经常用到的,今天学习排序的几大经典算法(python语言实现)。
目录
代码:
- def bubble_sort(alist):
- n = len(alist)
- for i in range(n - 1, -1, -1):
- for j in range(0, i):
- if alist[j] > alist[j + 1]:
- alist[j], alist[j + 1] = alist[j + 1], alist[j]
case:[22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70]
O(N^2)
有两层for循环, 看一下最差的情况
外层for循环,执行次数为N
内层for循环,第一次比较了n-1,第二次比较了n-2,……,第N-1次比较了1次,加起来,总的执行次数复杂度为N
复杂度为N*2
- def select_sort(alist):
- n = len(alist)
- for j in range(n - 1):
- min_index = j
- for i in range(j + 1, n):
- if alist[min_index] > alist[i]:
- min_index = i
- alist[j], alist[min_index] = alist[min_index], alist[j]
case:[22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70]
时间复杂度:N^2
循环了两次,外层循环和内层循环,时间复杂度为N^2
- def InsertionSort(aList):
- n = len(aList)
- for i in range(1, n):
- x = aList[i]
- j = i - 1
- while j >= 0:
- if x <= aList[j]:
- aList[j + 1] = aList[j]
- j -= 1
- else:
- break
- aList[j + 1] = x
case:[22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70]
N^2
需要循环两次,时间复杂度为N^2
- def ShellSort(aList):
- n = len(aList)
- gap = n // 2
- while gap > 0:
- for i in range(gap, n):
- x = aList[i]
- j = i
- while j >= gap:
- if x < aList[j - gap]:
- aList[j] = aList[j - gap]
- else:
- break
- j -= gap
- aList[j] = x
- print(aList)
- gap = gap // 2
希尔排序时间复杂度有点复杂,排序的效率是取决于它的增量序列。时间复杂度在O(nlogn~n^2)之间
- def Merge(aList, start, mid, end):
- tmp = []
- L = start
- r = mid + 1
- while L <= mid and r <= end:
- if aList[L] <= aList[r]:
- tmp.append(aList[L])
- L += 1
- else:
- tmp.append(aList[r])
- r += 1
- tmp.extend(aList[L:mid + 1])
- tmp.extend(aList[r:end + 1])
- for i in range(start, end + 1):
- aList[i] = tmp[i - start]
- print(start, end, tmp)
-
-
- def MergeSort(aList, start, end):
- if start == end:
- return
- mid = (start + end) // 2
- MergeSort(aList, start, mid)
- MergeSort(aList, mid + 1, end)
- Merge(aList, start, mid, end)
O(NlogN)
归并排序用到了递归和分治的思想,列表长度为N,用二分法分解,为logN,合在一起,复杂度是O(NlogN)
- def QucikSortPivot(aList, start, end):
- pivot = start
- j = start + 1
- for i in range(start + 1, end + 1):
- if aList[i] <= aList[pivot]:
- aList[i], aList[j] = aList[j], aList[i]
- j += 1
- aList[pivot], aList[j - 1] = aList[j - 1], aList[pivot]
- pivot = j - 1
- print(aList[pivot], aList[start:pivot], aList[pivot + 1:end + 1])
- return pivot
-
-
- def QuickSort(aList, start, end):
- if start >= end:
- return
- pivot = QucikSortPivot(aList, start, end)
- QuickSort(aList, start, pivot - 1)
- QuickSort(aList, pivot + 1, end)
随机快速排序
- import random
-
- def QucikSortPivot(aList, start, end):
- randIndex = random.randint(start,end)
- aList[start],aList[randIndex] = aList[randIndex],aList[start]
- pivot = start
- j = start + 1
- for i in range(start + 1, end + 1):
- if aList[i] <= aList[pivot]:
- aList[i], aList[j] = aList[j], aList[i]
- j += 1
- aList[pivot], aList[j - 1] = aList[j - 1], aList[pivot]
- pivot = j - 1
- print(aList[pivot], aList[start:pivot], aList[pivot + 1:end + 1])
- return pivot
-
-
- def QuickSort(aList, start, end):
- if start >= end:
- return
- pivot = QucikSortPivot(aList, start, end)
- QuickSort(aList, start, pivot - 1)
- QuickSort(aList, pivot + 1, end)
最坏时间复杂度:O(N^2)
- def SelectSort(aList):
- n = len(aList)
- for i in range(0, n):
- min = i
- for j in range(i + 1, n):
- if aList[j] < aList[min]:
- min = j
- aList[i], aList[min] = aList[min], aList[i]
-
-
- def BucketSort(aList):
- minV = min(aList)
- maxV = max(aList)
- bucketCount = 3
- bucket = [[], [], []]
- perBucket = (maxV - minV + bucketCount) // bucketCount
- for num in aList:
- buketIndex = (num - minV) // perBucket
- bucket[buketIndex].append(num)
- for i in range(bucketCount):
- SelectSort(bucket[i])
- index = 0
- for i in range(bucketCount):
- for v in bucket[i]:
- aList[index] = v
- index += 1
O(N^2)
最坏情况时间复杂度是O(N^2)
- def CountingSort(aList):
- n = len(aList)
- countLen = max(aList) + 1
- count = [0] * countLen
- for val in aList:
- count[val] += 1
- print(count)
- n = 0
- for val in range(0, countLen):
- while count[val] > 0:
- count[val] -= 1
- aList[n] = val
- n += 1
O(n+k)
第一次遍历数组,时间复杂度:O(n),第二次遍历计数器,(如果有k个计数器)时间复杂度O(K),加起来,时间复杂度为:O(n+k)
- def RadixSort(aList):
- base = 1
- maxv = max(aList)
- while base < maxv:
- bucket = []
- for index in range(10):
- bucket.append([])
- for num in aList:
- index = num // base % 10
- bucket[index].append(num)
- L = 0
- for index in range(10):
- for v in bucket[index]:
- aList[L] = v
- L += 1
- print(aList)
- base *= 10
O(n*k)
时间复杂度:O(n*k),其中n是输入元素的数量,k是数字的最大位数。
- def maxHeapify(heap, start, end):
- son = start * 2
- while son <= end:
- if son + 1 <= end and heap[son + 1] > heap[son]:
- son += 1
- if heap[son] > heap[start]:
- heap[start], heap[son] = heap[son], heap[start]
- start, son = son, son * 2
- else:
- break
-
-
- def HeapSort(aList):
- heap = [None] + aList
- root = 1
- L = len(heap)
- for i in range(L // 2, root - 1, -1):
- maxHeapify(heap, i, L - 1)
- for i in range(L - 1, root, -1):
- heap[i], heap[root] = heap[root], heap[i]
- maxHeapify(heap, root, i - 1)
- return heap[root:]
先来看看什么是堆,推荐阅读下面的这篇博客
建堆的时间复杂度为O(n),排序重建堆的时间复杂度为nlog(n),总的时间复杂度为O(nlogn)
针对具体的序列,每种排序算法复杂度都不同,具体要用到哪种排序算法,要结合实际案例,针对每种算法的时间复杂度的分析和应用,后面再做一下总结,此外,每种排序算法的代码要加以理解巩固!多练习几遍排序算法,达到熟练使用的程度。“无他,唯手熟尔”!