冒泡排序:
- 比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
def bubble_sort(array):
for j in range(len(array) - 1, 0, -1):
for i in range(j):
if array[i] > array[i + 1]:
array[i], array[i + 1] = array[i + 1], array[i]
return array
时间复杂度: 最优时间复杂度:O(n) (表示遍历一次发现没有任何可以交换的元素,排序结束。)
最坏时间复杂度:O(n**2)
稳定性:稳定
选择排序:
- 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
- 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
- 以此类推,直到所有元素均排序完毕。
def select_sort(array):
length = len(array)
for i in range(length):
min_index = i
for j in range(i + 1, length):
if array[j] < array[min_index]:
min_index = j
if min_index != i:
array[i], array[min_index] = array[min_index], array[i]
return array
时间复杂度:最优时间复杂度:O(n2)
最坏时间复杂度: O(n2)
稳定性:不稳定(考虑升序每次选择最大的情况)
插入排序
- 构建有序序列
- 对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入
- 插入排序在实现上,在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
def insert_sort(array):
length = len(array)
for i in range(1, length):
for j in range(i, 0, -1):
if array[j] < array[j-1]:
array[j], array[j-1] = array[j-1], array[j]
return array
时间复杂度:
最优时间复杂度:O(n) (升序排列,序列已经处于升序状态)
最坏时间复杂度:O(n**2)
稳定性:稳定
快速排序:
- 从数列中挑出一个元素,称为"基准"(pivot)
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
- 递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去
def quick_sort(array, start, end):
if start >= end:
return array
pivot = array[start]
low = start
high = end
while low < high:
while low < high and array[high] >= pivot:
high -= 1
array[low] = array[high]
while low < high and array[low] <= pivot:
low += 1
array[high] = array[low]
array[low] = pivot
quick_sort(array, start, low - 1)
quick_sort(array, low + 1, end)
return array
时间复杂度:
最优时间复杂度:O(nlogn)
最坏时间复杂度:O(n2)
稳定性:不稳定
希尔排序:
- 对要排序的列表根据一定间隔(初始间隔一般设为列表长度的一半)进行分组
- 对各列表之间相同位置(下标)的元素进行插入排序
- 间隔减半,再次分组并对各列表之间相同位置(下标)的元素进行插入排序
- 如此循环,最终间隔为1,即为正常的插入排序
def shell_sort(array):
length = len(array)
gap = length // 2
while gap > 0:
# 按步长插入排序
for i in range(gap, length):
while i >= gap and array[i - gap] > array[i]:
array[i - gap], array[i] = array[i], array[i - gap]
i -= gap
gap = gap // 2
return array
时间复杂度
最优时间复杂度:根据步长序列的不同而不同
最坏时间复杂度:O(n2)
稳定性:不稳定
归并排序:
- 假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2个长度为2或1的有序子序列,再两两归并,最终得到一个长度为n的有序序列为止,这称为2路归并排序。
def merge_sort(array):
if len(array) <= 1:
return array
num = len(array) // 2
left = merge_sort(array[:num])
right = merge_sort(array[num:])
return merge(left, right)
def merge(left, right):
print(left, right)
l, r = 0, 0 # 两个列表的起始位置指针
result = []
while l < len(left) and r < len(right):
if left[l] < right[r]:
result.append(left[l])
l += 1
else:
result.append(right[r])
r += 1
result += left[l:]
result += right[r:]
return result
时间复杂度:
最优时间复杂度:O(nlogn)
最坏时间复杂度:O(nlogn)
稳定性:稳定
基数排序:
- 按照个位数进行排序。
- 按照十位数进行排序。
- 按照百位数进行排序。排序后,数列就变成了一个有序序列。
def radix_sort(array):
mostBit = len(str(max(array)))
for i in range(mostBit):
bucket = [[] for _ in range(10)]
for j in array:
bucket[j//(10**i) % 10].append(j)
array = [j for i in bucket for j in i]
return array
时间复杂度:O(nlog®m),其中r为所采取的基数,而m为堆数
空间复杂度:O(n) 稳定性:稳定