堆排序

1 完全二叉树:若树的高度为H,那么除了H层的结点数可以小于2,其余层结点数都达到最大数。并且当H层结点数为1的时候,只能在左边。

2 堆是一个完全二叉树。分为大顶堆(max heap)和小顶堆(min heap)。

max heap:每个结点键值都不小于子结点。

min heap:每个结点键值都不大于子结点。

我们可以用数组来表示堆。

数组元素为1、2....7。很明显,第N个元素的父结点parent序号为N/2,左结点Left child序号为2N,右结点为2N+1

3 保持堆的性质(max heap)。A:用于表示堆的数组,下标从1开始,一直到n

void Heapify(int A[],int i)
{
    int l=LEFT(i);
    int r=RIGHT(i);
    int largest;
    if(l<=HEAP_SIZE(A)) largest=A[l]>A[i]?l:i;
        if(r<=HEAP_SIZE(A)) largest=A[r]>A[largest]?r:largest;  //从i,2*i,2*i+1中找出最大的一个
        if(largest!=i)    //i不是最大的
    {
        swap(A[i],A[largest]);
        Heapify(A,largest);  //交换后,子树有可能违反最大堆性质
    }
}

目的是保持第i个元素的堆性质。具体做法是将第i个元素和他的左右子结点进行比较,将最大的放到位置i。这个时候被转移的子结点可能违反堆性质,所以堆子结点继续保持堆性质。

4 建堆。注意建堆并不是依次插入元素,并保持堆的性质,而是建立一个完全二叉树后,

找到最后一个非叶子结点(总数为N,第N个结点的父结点N/2),保持堆的性质。并依次往上调整子树(依次往上选择下一个非叶子结点执行保持堆的性质)。

void BuildHeap(int A[])  
 {    
            int i;
            for(i = HEAP_SIZE(A)/2; i>=1; i--)    
               Heapify(A, i); 
  } 

5堆排序。

 先用BuildHeapo将数组A[1..n]构造成一个大顶堆。因为数组中最大元素在根A[1],则可以通过把它与A[n]交换来达到最终正确的位置。

void HeapSort(int A[])
{
    BuildHeap(A);
    for(i=HEAP_SIZE(A),i>1; i--)
    {
        swap(A[1],A[i]);
        HEAP_SIZE(A)=HEAP_SIZE(A)-1;
        Heapify(A,1);  //交换后新的根元素可能违背了最大堆的性质
    }
}
 

6 用途。

优先队列(c++里面的priority_queue):普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。

GETMAX:

void GetMaximum(int A[])   {
     int max = A[1];
     A[1] = A[n];
     HEAP_SIZE--;
     Heapify(A, 1);
     return max;
   } 

7 c++使用例子。

#include<queue>

int main(int argc, const char * argv[]) {
    std::priority_queue<int> que;
    que.push(2);
    que.push(4);
    que.push(3);
    que.push(1);
    que.push(5);
    
    int max = que.top();//取最大值
    
    printf("max---------------%d\n",max);//打印5
    
    que.pop();//移除最大值
    
    max = que.top();
    
    printf("max---------------%d\n",max);//打印4
    
    return 0;
}

转载于:https://my.oschina.net/yizhangxyz/blog/780228

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值