堆排序----赠品2

问题:

思路:

图解:

步骤1、将10个数,分为两组

步骤 2、对第一组进行堆排列

步骤3、将第二组数与第一组的堆排列的1进行比较,因0<1所以0被舍弃

步骤4、以此类推,7与1比较,因为7>1,所以7代替1,而1被舍弃,将7放入堆顶

步骤5、但是此时的堆并不是完备的,所以,进行完备操作,也就是把堆里最小的数放置在最顶部的位置上,如下:

步骤6、第二组剩下的2、4、5将继续重复步骤3、4、5直至第二组无数则停止

import time
import random

def cal_time(func):            # 装饰器 ,用来检测算法所执行的时间
    def wrapper(*args,**kwargs):
        t1=time.time()
        result=func(*args,**kwargs)
        t2=time.time()
        print("%s running time: %s secs." %(func.__name__,t2-t1))
        return result
    return wrapper

def sift(data,low,high):   # 调整函数
    i = low  # 树的根  也就是父亲 ,这里只领导
    j = 2 * i + 1 # 根的左孩子 也就是 儿子 ,这里指小领导
    tmp = data[i]  # 把根 取出来 做调整 , 在这里 领导
    while j <= high:  # high其实就是 根的右儿子(也就是最后一个儿子),如果 j= high 则表示没有右儿子,也就是说这里必须有儿子在
        if j + 1< high and data[j] > data[j + 1]: # j + 1< high 代表有右儿子 , data[j] < data[j + 1] 说明左儿子比右儿子大
            j += 1 # 这个 j 则变为右儿子 ,也就是 若有比 j 小的值,则 j 就变为比他小的那个值
        if tmp > data[j]: # 如果领导能干
            data[i] = data[j] # 则小领导上位
            i = j # 小领导变为大领导
            j = 2 * i + 1 # 小小领导变为小领导
        else: # 如果领导能干
            break # 那就待着吧
        data[i] = tmp # 到最后 i 这里肯定会有空位 ,所以无论 tem 是谁 都要占住这个空位

def topn(li,n): # li为列表 k为个数
    heap = li[0:n] # 存储的地方
    # 建堆
    for i in range(n // 2 - 1,-1,-1):
        sift(heap,i,n-1)
    # 遍历
    for i in range(n,len(li)):
        if li[i] > heap[0]: # 如果这个数 > 堆顶
            heap[0] = li[i] # 替代堆顶这个数
            sift(heap,0,n-1)
    for i in range(n - 1, -1, -1):  # n-1为high 也就是从堆得最后 一直到 0为止,也就是从刁民到领导
        heap[0], heap[i] = heap[i], heap[0]  # 堆的顶部 和 堆的末尾 互换, 也就是领导退休,刁民上位
        sift(heap, 0, i - 1)  # 0 代表着领导 ,i-1 代表着这个堆的位置不能把领导算在内了,也就是领导退休了,把他赶出这个城市了
    return heap

data = list(range(10000))
random.shuffle(data)
print(topn(data,10))

结果显示为:

原文地址:https://www.cnblogs.com/zhuifeng-mayi/p/9219758.html