堆的概念及实现
1.概述:
堆的概念:堆是一种完全二叉树,其高度为log(n),可以用一维数组来实现。堆中存储的数据是局部有序的。可分为两种堆:最大顶堆和最小顶堆。
最大顶堆:任意一个结点的值都大于等于其任意一个子结点的值。
最小顶堆:任意一个结点的值都小于等于其任意一个子结点的值。
可以发现,堆的罗辑结构是树状结构,而存储结构是线性结构,因此,堆常用来实现优先队列。还可又来堆排序等。
2.基本操作:
存储:显然,堆的元素可以保存在一维数组heap[]中,1表示根结点,结点k的父亲是k/2,左儿子是2×k,右儿子是2×k+1。
以最小顶堆为例:
① 向下调整:从根开始,选取当前结点 p 的较小的儿子结点;如果其值比 p 的值大,则调整停止。否则 p 和其儿子,继续调整。
② 向上调整:比较当前结点p和父节点,如果父节点的值比p小,则停止调整;否则交换父亲和p,继续向上调整。
③ 建立顶堆:从最后一个非终端结点即size/2处开始向下调整。
④ 删除堆顶:分为三步:1.直接删除根,2.用最后一个元素代替根,3.将堆向下调整。
⑤ 插入一个元素:分为两步:1.将元素添加到末尾,2.从末尾向上调整。
不难看出,基本操作其实就只有向下向上调整两个。
下面给出堆的类:
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #define _Clr(x, y) memset(x, y, sizeof(x)) 5 #define INF 0x3f3f3f3f 6 #define N 1010 7 using namespace std; 8 9 class HEAP 10 { 11 private: 12 int heap[N]; 13 int size; 14 public: 15 HEAP(){size=0;_Clr(heap, 0);} 16 void Make(int x) 17 { 18 size++; 19 heap[size] = x; 20 } 21 void Down(int p) 22 { 23 int q = p<<1; 24 int a = heap[p]; 25 while(q <= size) 26 { 27 if(q<size && heap[q+1]<heap[q]) 28 q++; 29 if(a <= heap[q]) break; 30 else 31 { 32 heap[p] = heap[q]; 33 p = q; 34 q = p<<1; 35 } 36 } 37 heap[p] = a; 38 } 39 void Up(int p) 40 { 41 int q = p>>1; 42 int a = heap[p]; 43 while(q>=1 && a<heap[q]) 44 { 45 heap[p] = heap[q]; 46 p = q; 47 q = p>>1; 48 } 49 heap[p] = a; 50 } 51 int GetTop() 52 { 53 int t = heap[1]; 54 heap[1] = heap[size--]; 55 Down(1); 56 return t; 57 } 58 void Insert(int x) 59 { 60 heap[++size] = x; 61 Up(size); 62 } 63 void BuildMinHeap() 64 { 65 for(int i=size>>1; i>0; i--) 66 Down(1); 67 } 68 }; 69 int main() 70 { 71 return 0; 72 }
以poj2051为例:
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #define _Clr(x, y) memset(x, y, sizeof(x)) 5 #define INF 0x3f3f3f3f 6 #define N 1010 7 using namespace std; 8 9 class HEAP 10 { 11 private: 12 struct Node 13 { 14 int id; 15 int p; 16 int t; 17 }heap[N]; 18 int size; 19 public: 20 HEAP(){size=0; _Clr(heap, 0);} 21 void Make(int id, int p, int i) 22 { 23 size=i; 24 heap[size].id = id; 25 heap[size].p = heap[size].t = p; 26 } 27 int GetTop() 28 { 29 int t = heap[1].id; 30 heap[1].t += heap[1].p; 31 Down(1); 32 return t; 33 } 34 void Down(int p) 35 { 36 int q = 2*p; 37 Node a = heap[p]; 38 while(q<=size) 39 { 40 if(q<size) 41 { 42 if(heap[q+1].t < heap[q].t) 43 q++; 44 else if(heap[q+1].t==heap[q].t && heap[q+1].id < heap[q].id) 45 q++; 46 } 47 if(a.t<heap[q].t || (a.t==heap[q].t && a.id<heap[q].id)) 48 break; 49 else 50 { 51 heap[p] = heap[q]; 52 p = q; 53 q = 2*p; 54 } 55 } 56 heap[p] = a; 57 } 58 void BuildMinHeap() 59 { 60 for(int i=size/2; i>0; i--) 61 Down(i); 62 } 63 void Print() 64 { 65 for(int i=1; i<=size; i++) 66 printf("%d ", heap[i].id); 67 puts(""); 68 } 69 }A; 70 71 int main() 72 { 73 char str[10]; 74 int i=1, id, p; 75 while(~scanf("%s", str) && strcmp(str, "#")) 76 { 77 scanf("%d%d", &id, &p); 78 A.Make(id, p, i); 79 i++; 80 } 81 A.BuildMinHeap(); 82 int k; 83 scanf("%d", &k); 84 for(int i=0; i<k; i++) 85 printf("%d\n",A.GetTop()); 86 return 0; 87 }