三种常用高级排序-堆排序,归并排序,快速排序

常用的高级排序代码整理

堆排序

基本思路

a.将无需序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;
b.将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;
c.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。

时间复杂度 空间复杂度 稳定性
最好 平均 最坏
O(nlogn) O(nlogn) O(nlogn) o(1) 不稳定
def sift(li,low,high):
    '''
    调整结构
    li:列表
    low:根节点
    high:子节点
    '''
    i = low # i最开始指向根节点
    j = 2 * i + 1 # j开始是左孩子节点
    tmp = li[i]
    while j <= high: #j超过最后一个节点,只要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 = i * 2 + 1
        else:       # tmp更大,则将tmp放在当前i的位置
            li[i] = tmp
            break
    else:
        li[i] = tmp # 把tmp放在最后
        
def heap_sort(li):
    n=len(li)
    for i in range((n-2)//2,-1,-1): #i表示建立堆的时候调整部分的根的下标
        sift(li,i,n-1)       #始终使用最后一个元素作为high,不会影响判断
    for i in range(n-1,-1,-1):  #i指向当前堆的最后一个位置
        li[0],li[i] = li[i],li[0]     # 堆首和堆尾交换位置,将最大的放到堆尾
        sift(li,0,i-1)      #i-1是新的high

python内部堆排序函数

import heapq
import random
li = list(rangen(100)
heapq.heapify(li)   #建立堆
heapq.heappop(li)   #弹出最小的值            

使用场景:

  • 热搜榜的取前几名

自己实现topk问题

基本思路

将前k个数建堆,从k+1个数开始遍历替换堆中的根节点并且调整堆,最后堆中留下来的元素就是最大或者最小且有序的

def sift(li,low,high):
    '''
    li:列表
    low:根节点
    high:子节点
    '''
    i = low # i最开始指向根节点
    j = 2 * i + 1 # j开始是左孩子节点
    tmp = li[i]
    while j <= high: #j超过最后一个节点,只要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 = i * 2 + 1
        else:       # tmp更大,则将tmp放在当前i的位置
            li[i] = tmp
            break
    else:
        li[i] = tmp # 把tmp放在最后

        
        
def topk(li,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)-1):
        if li[i] > heap[0]:
            heap[0] = li[i]
            sift(heap,0,k-1)
    # 遍历寻找topk
    for i in range(k-1,-1,-1):
        heap[0],heap[i] = heap[i],heap[0]
        sift(heap,0,i-1)
    #出数
    return heap

归并排序

基本思路

归并的基本思路在于先分解再合并,将数组分解为左右两个有序数组,然后将有序数组合并到一个数组中

时间复杂度 空间复杂度 稳定性
最好 平均 最坏
O(nlogn) O(nlogn) O(nlogn) o(n) 稳定

在这里插入图片描述

def merge(li,low,mid,high):
    '''
    合并左右两个有序数组
    '''
    i = low
    j = mid + 1
    ltmp = []
    while i <= mid and j<=high:   # 从两个数组的第一个元素开始,只要左右两边都有数
        if li[i] < li[j]:
            ltmp.append(li[i])
            i += 1
        else:
            ltmp.append(li[j])
            j +=1                   # 哪个元素小将其放入新数组的第一个
    while i<= mid:                  # 如果其中一边的数组都已经遍历完,则将另一边的顺序存入新数组中
        ltmp.append(li[i])
        i += 1
    while j<= high:
        ltmp.append(li[j])
        j += 1
    li[low:high+1] = ltmp           #将排好的新数组写回到原数组

    
def merge_sort(li,low,high):
    if low < high:                  #如果数组中的元素大于1则递归
        mid = (high + low) // 2
        merge_sort(li,low,mid)
        merge_sort(li,mid+1,high)
        merge(li,low,mid,high)

快速排序

基本思路

在数组中选中一个元素,将素组中所有小于该元素的元素放入左边,将大于该元素的元素放入右边,将该元素放于交界处,在将左右两边的数组分别按照上述逻辑接着整理,直到最小单元。

时间复杂度 空间复杂度 稳定性
最好 平均 最坏
O(n^2) O(nlogn) O(nlogn) 平均O(logn)最坏o(n) 不稳定
# 这种实现方法不需要开辟新的数组储存空间
def quick(li,left,right):
    '''
    将数组在区间内按照左中右排列
    '''
    i = left
    j = right
    base = li[i]
    while i < j:                           # 区间中还有元素
        while i<j and li[j] <= base:       # 将小于base的放在左边base的空位
            j=j-1
        li[i] =li[j]
        while i<j and li[i] >= base:       #将大于base的放在右边之前空出来的空位
            i = i + 1
        li[j] = li[i]
    li[i] = base                           #最后i=j的时候,将base放入
    return i                               # 返回中间值(base的索引)

def quick_sort(li,left,right):
    if left < right:
        mid = quick(li,left,right)
        quick_sort(li,left,mid - 1)
        quick_sort(li,mid + 1,right)

另一种快排

#这种需要占用其他的数组储存空间
def quick_sort2(li):
    if len(li)<2:
        return li
    else:
        base = li[0]
        lli = [i for i in li[1:] if i <=base]
        rli = [i for i in li[1:] if i >base]
        return quick_sort2(lli)+[base]+quick_sort2(rli)
发布了64 篇原创文章 · 获赞 46 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_42737442/article/details/95304351