1 冒泡排序
时间复杂度:O(n2),空间复杂度 O(1)
稳定性: 稳定
def bubble_sort(nums):
for i in range(len(nums)-1):
flag = False
for j in range(0, len(nums)-i-1):
if nums[j] > nums[j+1]:
swap(nums, j, j+1)
flag = True
if not flag:
break
return nums
注: swap函数
def swap(nums, i, j):
nums[i], nums[j] = nums[j], nums[i]
2 快速排序
时间复杂度:O(nlogn),空间复杂度 O(1)
时间复杂度: 每一轮需要比较n次, 需要比较logn轮
稳定性: 不稳定(相同的元素排序后可能会换位)
def partition(nums, left, right):
"""分割, 单边循环法, 把小于基准的放基准前面"""
pivot = left
i = j = pivot + 1 # i代表小于基准的位置, j代表当前遍历到的位置
while j <= right: # 没遍历完
if nums[j] < nums[pivot]: # 右边 比 基准小, 就交换
swap(nums, i, j)
i += 1
j += 1
swap(nums, pivot, i-1)
return i-1
def quick_sort(nums, left, right):
if left < right:
pivot = partition(nums, left, right)
quick_sort(nums, left, pivot-1)
quick_sort(nums, pivot+1, right)
3 选择排序
时间复杂度:O(n2), 空间复杂度 O(1)
稳定性: 不稳定
def select_sort(nums):
for i in range(len(nums)): # i记录当前的轮数
min_idx = i
for j in range(i+1, len(nums)):
if nums[j] < nums[min_idx]:
min_idx = j
swap(nums, i, min_idx) # 一轮结束后把最小的移到最前
4 堆排序
时间复杂度:O(nlogn), 空间复杂度 O(1)
时间复杂度: 每一轮需要比较logn次, 需要比较n轮
稳定性: 不稳定
def heapify(nums, i, size):
"""调整大顶堆"""
left, right = 2*i+1, 2*i+2 # 第i号结点的左子树和右子树
largest = i
if left < size and nums[left] > nums[largest]:
largest = left
if right < size and nums[right] > nums[largest]:
largest = right
if largest != i: # 若发现左右子树比父结点大, 则互换位置, 再继续向下调整堆
swap(nums, i, largest)
heapify(nums, largest, size)
def heap_sort(nums):
size = len(nums)
for i in range(size//2, -1, -1): # 构建大顶堆
heapify(nums, i, size)
for i in range(len(nums)-1, 0, -1): # 从最后一个结点(闭)遍历到倒数第一个结点(开)
swap(nums, 0, i) # 把最大的元素和最后的元素交换位置
size -= 1 # size-1, 最后的元素就是最大的, 不用再调整
heapify(nums, 0, size) # 把前面的元素继续调整为大顶堆
5 插入排序
时间复杂度:O(n2),空间复杂度 O(1)
稳定性: 稳定
def insert_sort(nums):
for i in range(1, len(nums)):
cur = nums[i] # 第i个数
pre_idx = i - 1
while pre_idx >=0 and nums[pre_idx] > cur: # 若之前的数大于第i个数, 往后挪
nums[pre_idx + 1] = nums[pre_idx]
pre_idx -= 1 # 跟前面的每一个数比较
nums[pre_idx + 1] = cur
6 希尔排序
时间复杂度:O(n2),空间复杂度 O(1)
稳定性: 不稳定
def shell_sort(nums):
n = len(nums)
gap = n // 2
while gap >= 1:
for i in range(gap): # i为每一个子序列起始元素的索引
j = i
while j+gap < n:
if nums[j+gap] < nums[j]: # 每一个子序列内排序
swap(nums, j, j+gap)
j += gap
gap //= 2
7 归并排序
时间复杂度:O(nlogn),空间复杂度 O(n)
稳定性: 不稳定
def merge(left, right):
"""排序, 合并"""
ret = []
while left and right:
if left[0] <= right[0]:
ret.append(left.pop(0))
else:
ret.append(right.pop(0))
ret.extend(left or right)
return ret
def merge_sort(nums):
"""对半分"""
if len(nums) < 2:
return nums
mid = len(nums) // 2
left, right = nums[:mid], nums[mid:]
return merge(merge_sort(left), merge_sort(right))