数据结构与算法(3)——二叉堆

 
  
 
  
#include < iostream >
using namespace std;
const int HEAP_SIZE = 100 ;
void sink( int fa);
void swim( int son);


int heap[HEAP_SIZE + 1 ];
int hs;
// 以建立最小堆为例

/* *************************************************************** */
// 删除堆顶元素 ,利用上游函数调整
/*

删除最小值(deleteMin) 先用最后一个元素代替根
由于这一步会导致根的元素比儿子大,因此需要向下调整。向下调整的方法很简
单,就是把根和较小儿子做比较,如果根比较大,则交换它和儿子,算
法好比石沉大海,因此有的书把它称为sink过程
*/
int deleteMin(){
int value = heap[ 1 ];
// 把堆尾元素前置,再sink()调整
heap[ 1 ] = heap[hs -- ];
sink(
1 );
cout
<< hs << endl;
for ( int i = 1 ;i <= hs;i ++ )cout << heap[i] << " " ;
cout
<< endl;
return value;
}
/* *************************************************************** */
// 下沉函数,辅助实现删除操作deleteMin()
void sink( int fa){
int son = fa << 1 ,a = heap[fa];
while (son <= hs){
// 使得son为两儿子中的较小值
if (son < hs && heap[son + 1 ] < heap[son])
son
= son + 1 ;
// 说明此时“fa”的位置很稳定
if (a <= heap[son])//千万别写成heap[fa]<=heap[son] !!!
break ;
// 物理上,为值得覆盖,逻辑上为两值的swap交换
heap[fa] = heap[son]; // son位置的数向上浮动
fa = son; // 循环迭代,以现在的son位置作为新的fa位置
son = fa << 1 ;

}
heap[fa]
= a;
}

/* *************************************************************** */
// 插入操作
/*

插入(insert) 插入是类似的,先插入到最后,然后向上调整。向上调整只需要比
较结点和父亲,比向下调整更容易。算法好比从海底游回水面,因此称为swim过程。
*/
void insert( int a){
heap[
++ hs] = a;
swim(hs);
}

/* *************************************************************** */
// 上游函数,辅助实现插入操作insert()

void swim( int son){
int fa = son >> 1 ,a = heap[son];
while (fa &&a < heap[fa]){
heap[son]
= heap[fa];
son
= fa;
fa
= son >> 1 ;
}
heap[son]
= a;
}

/* *************************************************************** */
// 初始建立一个堆
/*

给hs个整数,如何构造一个二叉堆?可以一个一个插入,但是有更好
的方法:从下往上一层一层向下调整。由于叶子无需调整,因此只需
要从[hs/2] 开始递减到1。
*/
void build(){
for ( int i = hs / 2 ;i >= 1 ;i -- )
sink(i);
for ( int i = 1 ;i <= hs;i ++ )cout << heap[i] << " " ;
cout
<< endl;
}

int main(){
cin
>> hs;
for ( int i = 1 ;i <= hs;i ++ )
cin
>> heap[i];
build();
cout
<< " 删除最小元素: " << deleteMin() << endl;
cout
<< " 删除第二小元素: " << deleteMin() << endl;
return 0 ;
}

二叉堆(binary heap) 是一个高级数据结构,它的思想简单,代码短,然而用处非常大。二叉堆一般被用来实现优先队列(priority queue)

优先队列经常被用来实现贪心算法和离散时间模拟系统,是一个基础数据结构。STL专门提供了priority queue 容器适配器,读者可以在学习本节后比较它和自己的二叉堆实现法的效率。二叉堆是一棵完全二叉树,即所有叶子在同一层,且集中在左边。二叉堆满足堆性质(heap property) :根的值在整棵树中是最小的。不仅如此,根的两棵树分别构成堆。用heap 数组来表示各个元素,则根是heap[1] ,最后一个元素是heap[n] ( heap[0]不使用)。

k 的左儿子是2k ,右儿子是2k + 1 ,父亲是bk=2c 。

转载于:https://www.cnblogs.com/liushang0419/archive/2011/05/08/2040485.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值