最小堆
在一些应用中,通常需要先收集一部分数据,从中挑选出具有最小或最大关键码的记录开始处理,接着,可能会收集更多的数据,并处理当前数据集中具有最大或最小关键码的问题。
这样的数据结构叫做堆,这里给出最小堆的实现。
堆是这样一种数据结构,其根结点都小于左右子女的完全二叉树。
1、插入算法:插入到最后一个结点,然后从下往上调整成最小堆。
2、删除算法:删除根结点,从上往下调整成最小堆。
3、从下往上调整算法。
4、从上往下调整算法。
两类错误:
1、while(parent>0) //while出错:因为while陷入死循环
SiftDown(parent); //递归到0
递归程序中还写了循环,一般会陷入死循环
2、-842150451 数组打印该值,数组越界
最下堆的抽象数据类型:
//最小堆抽象数据类型 class MinHeap { public: //构造函数和析构函数 MinHeap(int n); ~MinHeap(); //调整算法、插入和删除算法 void SiftDown(int start); //自下而上调整算法,用于插入 void SiftUp(int start); //自上而下调整算法,用于删除 bool InsertHeap(int x); //插入算法 int DeleteHeap(); //删除算法 void Output(); private: int *heap; //最小堆根指针 int count; //数组下标 };
/*
自下而上调整算法:
1、定义兄弟结点和父结点。
2、递归到一棵子树的根结点为止,因为最小堆性质,只要一直递归到根子树,
就可以保证最小堆的性质。
*/
void MinHeap::SiftDown(int start) { int parent=0; int temp=0; parent=(start-1)/2; //父结点,2i+1 2i+2 可以用这句话统一表达 if(heap[parent]>heap[start]) { //最小堆性质不满足,交换 temp=heap[parent]; heap[parent]=heap[start]; heap[start]=temp; } if(parent>0) //while出错:因为while陷入死循环 SiftDown(parent); //递归到0 }
/*
自上而下调整算法:最小堆,小的元素有聚类的效果,经验
1、
*/
void MinHeap::SiftUp(int start) { //从0开始到count-1结束 int st=start; int temp=0; int child=2*st+1; //从元素较小的子树开始递归 if(heap[2*st+1]<heap[2*st+2]) ; else child=2*st+2; if(heap[st]>heap[child]) { temp=heap[st]; heap[st]=heap[child]; heap[child]=temp; } if(2*child+1<=count-1) //递归 SiftUp(child); }
/*
插入算法:
1、将当前指针数组的值赋值为x。
2、如果是堆的根指针,则不做任何操作。
*/
bool MinHeap::InsertHeap(int x) { heap[count]=x; //赋值 if(count==0) { //根结点 count++; //自加1 return true; } else { //如果不是根结点 SiftDown(count); //从该结点开始调整为最小堆 count++; //自加1 return true; } }
/*
删除算法:
1、用最后一个结点代表根结点。
2、然后自上而下调整成最小堆。
*/
int MinHeap::DeleteHeap() { int x; x=heap[0]; //因为插入元素的时候位置指向下一个 heap[0]=heap[count-1]; //用最后一个元素代替 count--; //个数减1 SiftUp(0); //自上而下调整成最小堆 return x; }
测试结果:
-------------最小堆-----------
---------输出------
9 17 65 23 45 78 87 53
删除的结点:9
---------输出------
17 23 65 53 45 78 87
删除的结点:17
---------输出------
23 45 65 53 87 78
请按任意键继续. . .
最小堆的应用:
堆排序
最小生成树
海量数据处理Topn算法