堆是形如下图的二叉树
堆的最重要的性质,就是儿子的值一定不小于父亲的值。树的节点从上到下,从左到右的顺序紧凑排列。
【插入数据】push
首先在堆的末尾插入数据,然后不断向上提升直到没有大小颠倒
【删除数据】pop
从堆中删除最小的数据
先将堆中最后一个节点的值复制到根节点上,并且删除最后一个节点。然后不断向下交换,直到没有大小颠倒;
在向下交换的过程中,如果有两个儿子,则与其中较小的交换(如果儿子比自己小)。
【堆的操作复杂度】
两种操作都与树的深度成正比。 因此,如果有n个元素,那么每个操作的复杂度为O(logn);
【堆的实现】
给每个元素按照从上到下从左到右的顺序编号,并用数组来储存,此时儿子的编号满足如下性质
1.左儿子的编号是自己编号 x 2 + 1;
2.右儿子的编号是自己编号 x 2 + 2;
#include <iostream> using namespace std; const int maxn=10000; class priority_q{ public: priority_q(){ sz = 0; //size 初始化为0; } void push(int x); int pop(); int size(){ return this->sz; } private: int heap[maxn],sz; }; void priority_q::push(int x){ int i = sz++; while(i > 0){ // 父亲节点的编号 int p = (i - 1)/2; if(heap[p] <= x) break; //把父亲的节点放下来 heap[i] = heap[p]; //当前节点更新 i = p; } heap[i] = x; } int priority_q::pop(){ int ret = heap[0]; //根,最小值 int x = heap[--sz]; //最后一个节点, 放到根的数值 int i = 0; //从根向下交换 while(i * 2 + 1< sz){ int a= i * 2 + 1, b= i * 2 + 2; //两个儿子的位置 if(b < sz && heap[b]< heap[a]) a = b; //选出 最小的儿子 if(heap[a] >= x) break; //如果没有大小颠倒 退出 //把儿子的值提上来 heap[i] = heap[a]; i = a; } heap[i] = x; //最终在找到的位置 i 填入 x; return ret; } int main(){ priority_q pq; pq.push(5); pq.push(10); pq.push(7); pq.push(2); int size = pq.size(); for(int i = 0; i < size; i++){ cout<<"第"<<i+1<<"个数"<<pq.pop()<<endl; } return 0; }搞笑的是,在我敲完上面这段代码运行的时候,360说这个是木马!搞得我关掉360杀毒才成功运行
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/chaiwenjun000/article/details/47290823