常见八大排序算法
1 八大排序算法的时间复杂度和空间复杂度
排序算法 | 稳定性 | 平均时间复杂度 | 最差时间复杂度 | 空间复杂度 | 备注 |
---|---|---|---|---|---|
堆排序 | 不稳定 | O(nlogn) | O(nlogn) | O(1) | n大时较好 |
快速排序 | 不稳定 | O(nlogn) | O(n^2) | O(nlogn) | n较大时好 |
希尔排序 | 不稳定 | O(nlogn) | O(n^s) | O(1) | s时所选的分组 |
选择排序 | 不稳定 | O(n^2) | O(n^2) | O(1) | n较小时较好 |
基数排序 | 稳定 | O(logRB) | O(logRB) | O(n) | B是真数(0--9),R是基数 |
冒泡排序 | 稳定 | O(n^2) | O(n^2) | O(1) | n小时较好 |
插入排序 | 稳定 | O(n^2) | O(n^2) | O(1) | 大部分已排序时较好 |
归并排序 | 稳定 | O(nlogn) | O(nlogn) | O(1) | n大时较好 |
- 排序算法的稳定性
假定再待排序的记录序列中,存在多个相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在序列中,A1=A2,且A1字A2之前,而在排序后的序列中,A1任在A2之前,则称这种排序算法是稳定的,否则成为不稳定的。
2 各排序算法的python实现
2.1 冒泡排序(稳定)
nums = [1,3,1,4,5,9,12,1,11,135,12,3,45,67,89,23]
def bubbleSort(arr):
n = len(arr)
for i in range(n):
for j in range(0,n-i-1):
if arr[j]>arr[j+1]:
arr[j],arr[j+1] = arr[j+1],arr[j]
return arr
bubbleSort(nums)
2.2 归并排序(稳定)
def merge(list_left,list_right):
l,r = 0,0
new_list = []
while l < len(list_left) and r<len(list_right):
if list_left[l] <= list_right[r]:
new_list.append(list_left[l])
l += 1
else:
new_list.append(list_right[r])
r += 1
new_list += list_left[l:]
new_list += list_right[r:]
return new_list
def mergeSort(arr):
if len(arr) <= 1:
return arr
mid = len(arr)//2
list_left = mergeSort(arr[:mid])
list_right = mergeSort(arr[mid:])
return merge(list_left,list_right)
arr = [12,33,15,11,1,1334,122234]
res = mergeSort(arr)
print(res)
2.3 插入排序(稳定)
def insertSort(arr):
for i in range(len(arr)):
preIndex = i - 1
current = arr[i]
while preIndex >=0 and arr[preIndex] > current:
arr[preIndex+1]=arr[preIndex]
preIndex -=1
arr[preIndex+1] = current
return arr
nums = [1,4,7,2,5,8,3,6,9,0]
insertSort(nums)
2.4 基数排序 (稳定)
def radixSort(arr):
n = len(str(max(arr)))
for k in range(n):
bucket_list = [[] for i in range(10)]
for i in arr:
bucket_list[i//(10**k)%10].append(i)
arr = [j for i in bucket_list for j in i]
return arr
2.5 选择排序 (不稳定)
算法流程:
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
重复第二步,直到所有元素均排序完毕。
def selectionSort(arr):
for i in range(len(arr)-1):
minIndex = i # 记录最小数的索引
for j in range(i+1,len(arr)):
if arr[j]<arr[minIndex]:
minIndex = j
if i!= minIndex:
arr[i],arr[minIndex] = arr[minIndex],arr[i]
return arr
nums = [1,4,7,2,5,8,3,6,9,0]
selectionSort(nums)
2.6 快速排序 (不稳定)
def quickSort(arr,i,j):
if i >= j:
return []
pivot = arr[i] # 以第一个元素为基准
low = i
high = j
while i < j:
while i<j and arr[j]>=pivot:
j -= 1
arr[i] = arr[j]
while i<j and arr[i] <= pivot:
i += 1
arr[j] = arr[i]
arr[j] = pivot
quickSort(arr,low,i-1)
quickSort(arr,i+1,high)
return arr
2.7 希尔排序
def shellSort(arr):
n = len(arr)
gap = int(n/2)
while gap > 0:
for i in range(gap,n):
temp = arr[i]
j = i
while j >= gap and arr[j-gap] > temp:
arr[j] = arr[j-gap]
j -= gap
arr[j] = temp
gap = int(gap/2)
return arr
2.8 堆排序
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。
def heapify(arr, n, i):
largest = i
l = 2 * i + 1 # left = 2*i + 1
r = 2 * i + 2 # right = 2*i + 2
if l < n and arr[i] < arr[l]:
largest = l
if r < n and arr[largest] < arr[r]:
largest = r
if largest != i:
arr[i],arr[largest] = arr[largest],arr[i] # 交换
# 此时largest位置的数字(也就是最开始输入那个lis[i])处于待定状态,需要在它所有根部中确定其位置
heapify(arr, n, largest)
def heapSort(arr):
n = len(arr)
# Build a maxheap.
for i in range(n, -1, -1):
# 先把堆调整好小根堆的状态,在全堆中逐个调整每个数字的位置,调整的方法是在它所有根部中确定其位置
heapify(arr, n, i)
# 一个个交换元素
for i in range(n-1, 0, -1):
arr[i], arr[0] = arr[0], arr[i] # 交换
# 把新上来的0号安排到合适的位置上去,其中i指的是要调整的堆的范围
heapify(arr, i, 0)