介绍

堆,英文名heap。这个数据结构是来自于堆排序的,其结构近似于一颗完全二叉树,通常用数组来存储表示。堆是实现堆排序以及优先队列的基础数据结构。根据任何子树根节点都比左右孩子大或小,堆可以分为最大堆(又叫大根堆)和最小堆(又叫小根堆)。最大堆具有性质: 任何结点大于等于它左右孩子结点。最小堆则恰好相反:任何结点小于等于它左右孩子结点。

最小堆和最大堆如图所示:


如何建堆

对于给定的数组序列A,其长度为length,将它调整成符合堆的性质,成为建堆过程。下面以建立最大堆为例,讨论如何建堆。

由于最大堆需要满足任何结点都大于等于左右孩子结点,那么定义操作max_heapify。其作用是将结点调整为大于等于左右孩子结点,也就是从该节点,其左孩子,其右孩子中选取最大值作为该结点值,并与之原先结点进行交换,使得满足最大堆的性质。例如某结点值为5,其左右孩子分别为10, 3。经过max_heapfiy操作之后,该结点为10,其左右孩子为5, 3。如果该结点是与其左孩子交换的,继续调整左孩子,使得左孩子也满足该性质。这样递归调整下去,则使得整个结构满足最大堆。

由于数组的从[length/2] 到 length所对应的元素最后肯定是堆的叶子结点。则从[length/2]到1这些元素,必然是叶子结点的祖先,其中还肯定会有父亲结点。那么从[length、2]到1的过程中,利用max_heapify操作,从下到上动态调整堆,那么整个过程就是建堆的思路了。其伪代码如下

for i = [length/2] downto 1
 max_heapify(A, i);  // A 数组

时间复杂度分析

由于含有n个节点的完全二叉树最大高度为logn,则每一次调整时间复杂度为O(logn)。一共需要调整O(n)次,则时间复杂度为O(nlogn)。当然对于高度来说还不是最精确的计算,因为位于不同高度的结点,需要调整的最大次数是不一样的。因此还需要对不同高度的点进行讨论求和来计算精确的时间复杂度。

因为含有n个结点的堆最大高度为logn,而高度为h的堆最多包含个结点。因此有如下计算方法:




因此我们可以在线性时间内把一个无序数组构建成最大堆

实现代码

#include<stdio.h>

#define BLANK -9999
#define LENGTH 10

void max_heapify(int heap[], int i)
{

    int left = 2*i;
    int right = 2*i+1;
    int largest = i;

    if(left <= LENGTH && heap[left] > heap[i])
        largest = left;

    if(right <= LENGTH && heap[right] > heap[largest])
        largest = right;

    if(largest != i){
        int temp = heap[largest];
        heap[largest] = heap[i];
        heap[i] = temp;
        max_heapify(heap, largest);
    }

}

void build_heap(int heap[])
{
    for(int i=LENGTH/2; i>=1; i--)
        max_heapify(heap, i);
}

void print_heap(int heap[])
{
    for(int i=1; i<=LENGTH; i++)
        printf("%d ", heap[i]);
}

int main(void)
{
    int init_heap[LENGTH+1] = {BLANK, 4, 1, 3, 2, 16, 9, 10, 14, 8, 7}; // 第0个位置不存元素
    build_heap(init_heap);
    print_heap(init_heap);
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值