堆排序Python实现

首先说堆,什么是堆?

堆(默认大根堆)有两个特点:1.堆都是完全二叉树     2.堆的父节点的值都大于其孩子节点的值

其次我们要生成一个堆,也就是我们要从堆的最后一个父节点(度不为0的节点,按层次遍历数)开始往前依次进行堆化,以此递归的生成大根堆。

def  max_heapify(heap, heapSize, root):
    """堆化"""
    left = 2*root + 1
    right = 2*root + 2
    max_node = root
    
    if left < heapSize and heap[left] > heap[max_node]:
        max_node = left
    if right < heapSize and heap[right] > heap[max_node]:
        max_node = right
    if max_node != root:
        heap[max_node], heap[root] = heap[root], heap[max_node]
        max_heapify(heap, heapSize, max_node)

def build_max_heap(heap):
    n = len(heap)
    #从(heapSize -2)//2处开始调整,一直调整到第一个根节点
    for i in range((n-2)//2, -1, -1):
        max_heapify(heap, n, i)
    
    return heap

有了一个堆后我们就开始进行堆排序,堆排序就是将堆的根节点与最后一个节点进行交换,因为已经是大根堆所以根节点一定是最大的值。交换后再将当前最后一个节点弹出,再把当前的二叉树堆化,以此规律进行下去,直到堆的所有元素均弹出。

def  max_heapify(heap, heapSize, root):
    left = 2*root + 1
    right = 2*root + 2
    #父节点i的左子节点在位置(2*i+1);
    #父节点i的右子节点在位置(2*i+2);
    max_node = root
    
    if left < heapSize and heap[left] > heap[max_node]:
        max_node = left
    if right < heapSize and heap[right] > heap[max_node]:
        max_node = right
    if max_node != root:
        heap[max_node], heap[root] = heap[root], heap[max_node]
        max_heapify(heap, heapSize, max_node)

def build_max_heap(heap):
    n = len(heap)
    #从(heapSize -2)//2处开始调整,一直调整到第一个根节点
    for i in range((n-2)//2, -1, -1):
        max_heapify(heap, n, i)
    
    return heap

#heap = [4, 10, 3, 5, 1, 2]
#heap = [50,16,30,10,60,90,2,80,70]  
#build_max_heap(heap)

def heap_sort(heap):
    heap = build_max_heap(heap)
    n = len(heap)
    alist = []
    for i in range(n-1, -1, -1):
        heap[0], heap[-1] = heap[-1], heap[0]
        alist.append(heap.pop(-1))
        max_heapify(heap, len(heap), 0)
    #alist = alist + heap
    
    return alist
        
heap = [50,16,30,10,60,90,2,80,70]
heap = [54,26,93,17,77,31,44,55,20]
heap_sort(heap)

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值