TopK问题

 

 

 

#堆排序
#可用

#1、建一个完全二叉树
#2、调整为一个初始堆,为大根堆,第一个值最大
#3、进行堆排序,调整为小根堆,最后一个值最大
#4、topK问题,剩余的n-k个数与已排好序的小根堆进行比较

#对数组来说,以下标index为根节点的左右子树的下标为 index * 2 + 1, index * 2 +  2
# 将length个元素,i为节点的数组堆化(i的子节点也都是堆)
def big_heap_array(array, i, length):
    # 左叶子节点
    temp_value = array[i]
    node_index = (i << 1) + 1
    while node_index < length:
        # print("1==node_index={}".format(node_index))
        #左右叶子节点的较大值
        if node_index + 1 < length and array[node_index + 1] > array[node_index]:
            node_index = node_index + 1
            # print("2==node_index={}".format(node_index))
        # 如果根节点大于叶子节点,说明已经是堆,退出循环。
        if array[node_index] < temp_value:
            # print("array={}".format(array))
            break
        array[i] = array[node_index] #交换i与node_index的下标的值
        # 调整交换过元素的子节点
        i = node_index
        # print("i={}".format(i))
        node_index = (i << 1) + 1
        # print("3==node_index={}".format(node_index))
    # print("array[i]={}".format(array[i]))
    array[i] = temp_value #最后一个值与根节点调换


#建一个完全二叉树,即一个无序数组
#2、调整为一个初始堆,为大根堆,第一个值最大
def build_heap(array, length):
    #从最后一个非叶子节点开始比较
    last_parent = length >>1  #最后一个根结节点下标[size/2-1]
    for last_parent in range(last_parent,-1,-1):
        big_heap_array(array, last_parent, length)
    
     # 堆顶最大值和最后一个数互换, 然后对大根堆进行排序,从小到大排序,
     # 最大一个值为最大值,为一个小根堆
    for index in range(length - 1, 0, -1):
        array[0], array[index] = array[index], array[0]
        big_heap_array(array, 0, index)


if __name__ == "__main__":
    #大顶堆排序
    lst = [2,3,6,1,9,5,8,10,21,20,80,76,33,99,100]
    lst1 = []
    lst1 = lst[0:10]
    print('source lst1:',lst1)
    build_heap(lst1, len(lst1))
    print("sort lst1:", lst1)
    #lst [1, 2, 3, 5, 6, 8, 9, 10],结果为这个
    #遍历剩余的n-k个数据,寻找最大的topk个
    # for index in range(len(lst1), len(lst)):
    #     #与堆顶元素比较
    #     comptemp = lst[index]
    #     if comptemp > lst1[0]:
    #         #如果大于堆顶值,进行交换,然后对堆进行排序
    #         lst1[0] = comptemp
    #         build_heap(lst1,len(lst1))
    #     else:
    #         continue
    # print('source lst: ',lst )
    # print("sort topK lst", lst1)

    #遍历剩余的n-k个数据,寻找最小的的topK个
    for index in range(len(lst1), len(lst)):
        #与堆顶元素比较
        comptemp = lst[index]
        if comptemp < lst1[0]:
            #如果大于堆顶值,进行交换,然后对堆进行排序
            lst1[0] = comptemp
            build_heap(lst1,len(lst1))
        else:
            continue
    print('source lst: ',lst )
    print("sort topK lst", lst1)
    #程序证明是正确的
原文地址:https://www.cnblogs.com/shmily2018/p/11502613.html