堆的 两种实现 (数组和STL)

 

基本思想: 两种操作都跟树的深度成正比,所以复杂度  O(log(n)) ;

push():在向堆中插入数值时,首先在堆的末尾插入该数值,然后不断向上提直到没有大小颠倒为止。

pop(): 从堆中取出一个数值时,首先把堆的最后一个节点的数值复制到根节点上,并且删除最后一个节点,然后不断向下交换直到没有大小颠倒为止,在向下交换的时候,如果有两个儿子,那就选择数值较小的(如果可以交换的话)进行交换。

 

数组实现:

 1 #include <cstdio>
 2 const int maxn = 10000;
 3 int heap[maxn], sz=0;
 4 
 5 void push(int x) {
 6     int i = sz++;
 7     while(i > 0) {
 8         int p = (i-1) / 2;  //p是父亲节点的编号
 9         if(heap[p] <= x) break;  //如果没有大小颠倒则退出
10         heap[i] = heap[p];  //把父亲节点 放下来 ,而把自己提上去
11         i = p;
12     }
13     heap[i] = x;  //把 x放入 正确的位置
14 }
15 
16 int pop() {
17     int ret = heap[0]; //最小值
18     int x = heap[--sz]; //要提到根的数值
19 
20     int i = 0;  //从根开始向下交换
21     while(i * 2 + 1 < sz) {   //可能 只有 一个  儿子
22         int a = i * 2 + 1, b = i * 2 + 2;  //两个儿子的 编号
23         if(b < sz && heap[b] < heap[a]) a=b;  //如果 右儿子存在 并且 值比 左儿子小 则交换
24         if(heap[a] >= x) break; //如果不能交换 就退出
25         heap[i] = heap[a];  //把儿子的  数值提上来
26         i=a;
27     }
28     heap[i] = x;
29     return ret;
30 }
31 
32 int main()
33 {
34     push(1);
35     push(2);
36     push(10);
37     push(7);
38     push(4);
39 
40     int x1 = pop();
41     int x2 = pop();
42 
43     printf("%d %d\n",x1,x2);
44     for(int i = 0; i< sz; i++)
45         printf("%d ", heap[i]);
46     return 0;
47 }

 

STL:

priority_queue 默认取出的是最大值。

priority_queue<int, vector<int>, greater<int> >que; 从小到大

priority_queue<int, vector<int>, less<int> >que;     从大到小

 1 #include <iostream>
 2 #include <queue>
 3 using namespace std;
 4 
 5 int main() {
 6     priority_queue<int> que;
 7 
 8     que.push(5);
 9     que.push(2);
10     que.push(1);
11 
12     while(que.size()) {
13         cout << que.top() << endl;
14         que.pop();
15     }
16     return 0;
17 }

 

posted @ 2015-05-05 14:26  NowAndForever  阅读(462)  评论(0编辑  收藏  举报