学个排序~
前言
该补充的算法基础还是要补TuT
快排(Quick Sort)
思路总结:
以某个位置为轴,大于轴的数都移动至右侧,小于轴的数都移动到左侧,轴左右侧的新列表递归选取轴和按大小排列
复杂度:
平均:O(nlogn); 最差:O(n^2)
代码:
def quick_sort(A):
quick_sort2(A, 0, len(A)-1)
def quick_sort2(A, low, hi):
# 递归方法
if hi > low:
p = partition(A, low, hi)
quick_sort2(A, low, p-1)
quick_sort2(A, p+1, hi)
def partition(A, low, hi):
# 获取轴
# [轴, 小于轴, 小于轴, 小于轴, 大于轴, 大于轴, 大于轴, 大于轴]
# [小于轴, 小于轴, 小于轴, 轴, 大于轴, 大于轴, 大于轴, 大于轴]
# 返回轴
privot = get_privot(A, low, hi)
privot_value = A[privot]
A[low], A[privot] = privot_value, A[low]
border = low
for i in range(low+1, hi+1):
if A[i] < privot_value:
border += 1
A[i], A[border] = A[border], A[i]
A[low], A[border] = A[border], A[low]
return border
def get_privot(A, low, hi):
# 选取一个位置为轴
# 若不选取中间值为轴 最差O(n^2)
mid = (hi + low) // 2
s = sorted([A[hi], A[low], A[mid]])
if s[1] == A[hi]:
return hi
elif s[1] == A[low]:
return low
else:
return mid
插入排序(Insertion Sort)
思路:
从左往右,拿起一个数,向左侧找它应该插入的位置
复杂度:
O(n^2)
代码:
def insert_sort(A):
n = len(A)
for i in range(1, n):
# 拿起一个元素
cur_val = A[i]
k = 0
# 比它大的都往右挪一格
for j in range(i-1, -2, -1):
k = j
if cur_val < A[j]:
A[j+1] = A[j]
else:
break
# 挪出来空的一格把该元素放入
A[k+1] = cur_val
选择排序(Selection Sort)
思路:
从左往右,找最小值放到最左边
复杂度:
O(n^2)
代码:
def select_sort(A):
n = len(A)
for i in range(0, n):
# 找出A[i:end]中的最小值
min_idx = i
for j in range(i+1, n):
if A[j] < A[min_idx]:
min_idx = j
# 将这个最小值交换值A[i]的位置
if min_idx != i:
A[min_idx], A[i] = A[i], A[min_idx]
冒泡排序(Bubble Sort)
思路:
从左往右,左侧比右侧大,则交换;一直交换至最右侧,依次排出:第n位为0至n的最大值,第n-1位为0至n-1的最大值
复杂度:
O(n^2)
代码:
def bubble_sort(A):
n = len(A)
for i in range(n):
for j in range(0, n-i-1):
if A[j] > A[j+1]:
A[j], A[j+1] = A[j+1], A[j]
归并排序(Merge Sort)
思路:
将列表分为两份,分别对左侧和右侧进行归并排序,排序完之后比较左侧和右侧第一个的大小,小的先放进结果中,再取下一个较小的放入结果,直至取完所有结果
复杂度:
O(nlogn)
代码:
def merge_sort(A):
merge_sort2(A, 0, len(A)-1)
def merge_sort2(A, first, last):
if last > first:
# 拆分为左右两组 分别归并排序
mid = (first+last) // 2
merge_sort2(A, first, mid)
merge_sort2(A, mid+1, last)
# 合并左右结果
merge(A, first, mid, last)
def merge(A, first, mid, last):
left = A[first:mid+1]
right = A[mid+1:last+1]
left.append(9999999999)
right.append(9999999999)
i = j = 0
# 依次取左右较小的作为第A[k]值,直至拼接成完整的A[first:last+1]
for k in range(first, last+1):
if left[i] <= right[j]:
A[k] = left[i]
i += 1
else:
A[k] = right[j]
j += 1