/****************************************************************************************
* (1) 显然索引为i的节点的子节点为区间 [ d*(i-1)+2,d*(i-1)+d+1 ];
* (2) logdN;
* (3) 见下面_adjust()函数,运行时间为:Θ(d*logdN);
* (4) 见下面_insert()函数,插入单个元素运行时间为:Ο(logdN),最坏情形也就这样了;
* (5) 该问要求实现最大优先队列中的一个以d堆为基的函数:将元素x的关键字的值增加到k,同时保持最大(小)堆性质。很简单,直接更新x键值,再执行_adjust()即可。
****************************************************************************************/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | #include<iostream> using namespace std;
const int d=3;
//调整法建堆实际上是自顶而下的,后面的插入法则是自下而上 void _adjust(int a[],int holeIndex ,int n) { int j=d*( holeIndex -1)+2; int item=a[holeIndex]; while(j<=n) { int sub_max=a[j],pos=j; for(int k=1;k<d;k++){ //在d个子节点中寻找最大子节点 if((j+k<=n)&&(sub_max<a[j+k])){ sub_max=a[j+k]; pos=j+k; //存储最大子节点的下标 } } if(item<sub_max) a[holeIndex]=sub_max; holeIndex=pos; j= d*( holeIndex -1)+2; } a[holeIndex]=item; }
//以下为测试程序 int main() { int a[13]={0,4,1,3,2,16,7,9,10,14,8,23,5}; for(int i=12/d;i>0;i--){ _adjust(a,i,12); } for(int i=1;i<=12;i++) cout<<a[i]<<" "; cin.get(); return 0; }
//_insert()函数
#include<iostream> using namespace std;
const int d=3; int a[13]={0,4,1,3,2,16,7,9,10,14,8,23,5}; int b[13]={0};
void _insert(int b[],int value,int n) { int i=n; while((i>1)&&(b[(i-2)/d+1]<value)){ b[i]=b[(i-2)/d+1]; i=(i-2)/d+1; } b[i]=value; }
int main() { for(int i=1;i<=12;i++){ _insert(b,a[i],i); } for(int i=1;i<=12;i++) cout<<b[i]<<" "; cin.get(); return 0; } |