数据结构之堆(Heap)

详情见代码中的注释

/*
* 堆的性质
* 堆中某个节点的值总是不大于或不小于其父节点的值(小顶堆或大顶堆)
* 堆总是一棵完全二叉树 
* 
* 由于堆是一个完全二叉树,所以我们可以用数组模拟树
* 第i个结点的父结点是第i/2个结点
* 第i个结点的左子女是第2*i个结点
* 第i个结点的右子女是第2*i+1个结点
* 
* 堆的应用
* 堆排序   优先队列 
*/
//-------------------
/*
* 维持堆的基本性质 
* 假定pos的左子树和右子树都已经是一个堆
* 然后调整pos,使它满足堆的性质 
*/
void Heapify(int a[N], int length, int pos){
    int left = pos*2;//左子女 
    int right = pos*2+1; //右子女 
    int largest = pos;
    //pos,left,right中寻找最大值 
    if (length >= left){ 
        largest = a[largest] >= a[left] ? largest : left;
    }
    if (length >= right){
        largest = a[largest] >= a[right] ? largest : right;
    }
    if (largest != pos){
        swap(a[largest], a[pos]); //交换最大值 
        Heapify(a, length, largest); //交换后子树有可能不满足堆的性质 
    }
}
/*
* 建立一个堆 
* 将数组a转换成一个大顶堆
* 先找到最后一个非叶子结点(即第n/2个结点,因为堆是一个完全二叉树) 
* 从这个结点开始,从后往前调整每个子树,使之满足堆的性质
* 最后整个数组都满足堆的性质
* 因为a[n/2+1...n]都是叶子结点,可以看做只有一个结点的堆 
*/
void BuildHeap(int a[N], int length){
    for (int i = length/2; i > 0; i--){
        Heapify(a, length, i);
    }
}
/*
* 堆排序算法
* 先构造一个大顶堆,此时a[1]是最大值,
* 把它和a[length]交换,然后将length减一,再调整堆
* 
* 如果要升序,则建立一个大顶堆
* 如果要降序,则建立一个小顶堆
* 
*/
void HeapSort(int a[N], int length){
    BuildHeap(a, length);
    for (int i = length; i > 0; i--){
        swap(a[i], a[1]);
        Heapify(a, i-1, 1);
    }
}
/*
* 优先队列 priority_queue 
* 
* 删除队列中的最大值
* 参数说明:数组a已经是一个堆
* a[1]就是最大值
* 将a[length]赋给a[1],然后length减一
* 调整堆 
*/
void DelMax(int a[], int &length) {
    a[1] = a[length];
    length--;
    Heapify(a, length, 1);
}
/*
* 获取队列的最大值 
*/
int GetMax(int a[], int length) {
    return a[1];
}
/*
* 插入
* 向堆中插入一个元素value, 同时仍然保持堆的性质
* 将value放在最后面,然后从下向上调整,使a仍保持堆的性质 
*/
void insert(int a[], int &length, int value) {
    length++; 
    int pos = length;
    while(pos > 1 && a[pos/2] < value){
        a[pos] = a[pos/2];
        pos /= 2;
    }
    a[pos] = value;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值