堆這種數(shù)據(jù)結(jié)構(gòu)呢,就是一種能保證堆頂元素是最大元素,或最小元素的一種數(shù)據(jù)結(jié)構(gòu),維護(hù)時間為log2 N
下面介紹我們就拿最大堆來說,不失一般性
首先說堆的結(jié)構(gòu):堆的結(jié)構(gòu)就一個要求,根節(jié)點大于他的兩個子節(jié)點
首先說元素的刪除,我們只能刪除堆頂元素
我們刪除堆頂元素后將堆尾元素heap【top】與堆頂元素heap【1】交換 此時堆的長度top=top-1;
然后找到他的子節(jié)點中較大的那個 :t
如果此元素大于子節(jié)點中較大的那個,就交換 并且繼續(xù)往下找,直到一直找到堆尾
否則,維護(hù)完成,退出維護(hù)
int k=1;heap[k]=heap[top--];//將堆尾元素移到堆首while (k*2<=top){ int t=k*2; if (t<top&&compare(heap[t+1]),heap[t]<0) t++;//t為結(jié)點k左右結(jié)點中較小的那個 if (compare(heap[k],heap[t])<0) {Swap(heap[t],heap[k]);k=t;} else break;}再說元素的進(jìn)入我們將新讀入的元素放在堆尾
然后一個一個往上維護(hù)
while (k>1){ int t=k/2; if (compare(heap[t],heap[k])>0) {Swap(heap[t],heap[k]);k=t;} else break;}對于結(jié)構(gòu)體來說就要寫自己的compare了下面是一個結(jié)構(gòu)體的例子
題目為 zoj2724
#include <cstdio>#include <cstring>using namespace std;const int maxn=60010;const int maxs=100;struct info{ char name[maxs]; int para,PRi,t;}p[maxn];int compare(int a,int b){ if (p[a].pri<p[b].pri) return -1; if (p[a].pri>p[b].pri) return 1; if (p[a].t<p[b].t) return -1; if (p[a].t>p[b].t) return 1; return 0;}void Swap(int&a,int&b){ int c; c=a;a=b;b=c; return;}int heap[maxn];int top,used;int main(){ used=0; top=0; int cnt=0; while (scanf("s",s)!=EOF) { if (!strcmp(s,"GET")) { if (top) { printf("%s %d",p[heap[1]].name,p[heap[1]].para);//輸出堆頂元素 int k=1; heap[k]=heap[top--];//將堆尾元素移到堆首 while (k*2<=top) { int t=k*2; if (t<top&&compare(heap[t+1]),heap[t]<0) t++;//t為結(jié)點k左右結(jié)點中較小的那個 if (compare(heap[k],heap[t])<0) {Swap(heap[t],heap[k]);k=t;} else break; } } else printf("EMPTY QUEUE!/n"); } else { scanf("%s%d%d",p[used].name,&p[used].para,&p[used].pri);//將used作為緩沖區(qū) p[used].t=cnt++; int k=++top; heap[k]=used++; while (k>1) { int t=k/2; if (compare(heap[t],heap[k])>0) {Swap(heap[t],heap[k]);k=t;} else break; } } } return 0;}//堆這種數(shù)據(jù)結(jié)構(gòu)就是能保證第一個是最大值或者最小值并且邊輸入遍維護(hù)的
新聞熱點
疑難解答