2.7 算法 --8 堆排序

算法子目录://www.greatytc.com/p/02492be3c5f5

堆排序

堆排序依赖堆的向下调整性质。


流程示意图

流程

流程1
流程2
流程3
流程4
流程5
流程6

我们提取根节点上的元素,并把它删除,那么堆会自动把最大的放在根节点上,然后周而复始,直至堆没有元素。

代码

from cat_time import cal_time
import random

def sift(li,low,high):
    #li表示树,low表示high的父节点,high表示树的最后一个节点
    tmp = li[low]
    i = low
    j = 2 * i + 1  #初始j指向左子节点
    # i 指向空位,j指向子节点
    while j <= high: #退出的第二种情况:j大于high,说明空
        if j + 1 <= high and li[j] < li [j+1]:#如果右子节点存在,且大于左子节点
            j += 1   #则使用右子节点
        if li[j] > tmp:
            #这里比较 li[j] 与 li[j] 的父节点 li[i] 的大小,如果 li[j] 大于 li[i] ,则交换。
            li[i] = li[j]
            # 同时,让i保存j的位置,j再保存相应的左子节点。 接着到while进行判断 j还在不在堆的范围中。
            i = j
            j = 2 * i + 1
        else: #退出的第一种情况:j的位置比tmp小,说明两个子节点都比tmp小。
            break
    li[i] = tmp  #把拿出来的那个值放在空位上面。
@cal_time
def heap_sort(li):
    n = len(li)
    # 构造堆
    for low in range(n//2-1,-1,-1):
        sift(li,low,n-1)
    #挨个出数
    for high in range(n-1,-1,-1):
        #将根和high换位,这样就可以将空间复杂度降到O(1)
        li[0],li[high] = li[high],li[0]
        #high-1是划分出堆区与有序区
        sift(li,0,high-1)

li = list(range(10000))
random.shuffle(li)
heap_sort(li)
print(li)

heapq

这是一个堆排序的内置库,但是很不方便,只有小根堆排序。

import heapq

li = list(range(10))
random.shuffle(li)

#排序
heapq.heapify(li)

#按顺序将一个元素入队
heapq.heappush(li,0.1)
print(li)

#将最小的元素出队
item = heapq.heappop(li)
print(li)

def heapsort(li):
    h = []
    for value in li:
        heapq.heappush(h,value)
    return [heapq.heappop(h) for i in range(len(h))]

print(heapsort(li))

总结

稳定性:堆排是一种不稳定排序。

比较性:因为排序时元素之间需要比较,所以是比较排序

时间复杂度:时间复杂度为O(nlogn)

空间复杂度:空间复杂度可以是O(1),可以是O(n)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容