总结三种速度较快的排序方法:快速排序、堆排序、归并排序
· 三种排序算法的时间复杂度都是O(nlogn)
· 一般情况,就运行速度: 快速排序>归并排序>堆排序
· 三种排序算法的缺点:
· 快速排序:极端情况(倒叙)下排序效率低
· 归并排序: 需要额外的内存开销
· 堆排序: 在快的排序算法中相对较慢
快速排序
def partition(li, left, right):
tmp = li[left] # 先把第一个值取出来 这样左边先出现一个空位
while left < right:
while left < right and li[right] >= tmp: # 从右开始找比tmp小的值
right -= 1 # right箭头左移一位
li[left] = li[right] # 将右边的大值写到左边的空位
while left < right and li[left] <= tmp: # 从左边开始找比tmp大的值
left += 1
li[right] = li[left]
li[left] = tmp # 把取出来的第一个值归位
return left
def quick_sort(li, left, right):
if left < right:
mid = partition(li, left, right)
quick_sort(li, left, mid-1)
quick_sort(li, mid+1, right)
堆排序
# 注意建立的是小根堆
def sift(li, low, high):
i = low # i最开始志向堆的根节点
tmp = li[i] # 把i位置上的值取出来
j = 2 * i + 1 # j是左叶子节点
while j <= high: # 只要j的位置有数,就一直循环
if j + 1 <= high and li[j+1] < li[j]:
j = j + 1 # 让j指向右孩子
if li[j] < tmp:
li[i] = li[j]
i = j
j = 2 * i + 1
else: # tmp更大 写回去
li[i] = tmp
break
else:
li[i] = tmp
def topk(li, k):
# 选前k个数,建立小根堆
heap = li[0:k]
for i in range((k-2)//2, -1, -1):
sift(heap, i, k-1)
# 遍历剩下的数,与堆顶元素比较
for i in range(k, len(li)):
if i > heap[0]:
heap[0] = i
sift(heap, 0, k-1)
# 小根堆建立完成 此时最大的数再最后,出数即可
for i in range(k-1, -1, -1):
heap[i], heap[0] = heap[0], heap[i]
sift(heap, 0, i-1)
return heap
归并排序
def merge(li, low, mid, high):
i = low
j = mid + 1
li_tmp = []
while i <=mid and j <= high: # 只要两边都有数
if li[i] < li[j]:
li_tmp.append(li[i])
i += 1
else:
li_tmp.append(li[j])
j += 1
# 上面的while执行完,左右两部分肯定有一部分没数了
while i <= mid:
li_tmp.append(li[i])
i += 1
while j <= high:
li_tmp.append(li[j])
j += 1
# 此时,li_tmp已经存好了排好序的内容,再写回li
li[low:high+1] = li_tmp
def merge_sort(li, low, high):
if low < high:
mid = (low + high)//2
merge_sort(li, low, mid)
merge_sort(li, mid, high)
merge(li, low, mid, high)