模板:堆
做点好人好事攒点RP:浙大acm模板.pdf
度盘:https://pan.baidu.com/s/1slLnJHF
最近看到一个堆的模板(浙大的acm模板),贴过来
#define MAXN 10000 #define _cp(a,b) ((a)<(b)) typedef int elem_t; struct heap{ elem_t h[MAXN]; int n,p,c; void init(){n=0;} void ins(elem_t e){ for (p=++n;p>1&&_cp(e,h[p>>1]);h[p]=h[p>>1],p>>=1); h[p]=e; } int del(elem_t& e){ if (!n) return 0; for (e=h[p=1],c=2;c<n&&_cp(h[c+=(c<n-1&&_cp(h[c+1],h[c]))],h[n]);h[p]=h[c],p=c,c<<=1); h[p]=h[n--];return 1; } };
代码倒是写的很好,又快又短,而且封装性很好,水平和我看过的几个STL原型差不多了
至少比我写的又慢又长而且封装性差的一批(最重要的是我打的是错的)的堆写的好多了
然而很难懂,如果硬背的话估计会打错,要是打错了估计调试一辈子都调不出来
所以我就手动把这些代码翻译成了正常的(误)C++语言
首先来一个我自己打的堆(调试了一上午终于打对了)
#include <stdio.h> #define MAXN 3000000 #define SWAP(a, b) ((a)^=(b),(b)^=(a),(a)^=(b)) struct heap { int H[MAXN], cnt; inline void push(int a) { int s, f; H[++cnt] = a; s = cnt, f = (s>>1); while(s > 1 && H[s] < H[f]) { SWAP(H[s], H[f]); s = f; f = (s>>1); } } inline int pop() { if(cnt < 1) return -1; int ret = H[1]; H[1] = H[cnt--]; int s = 2, f = 1; while(s <= cnt) { if(s < cnt && H[s] > H[s+1]) s++; if(H[f] > H[s]) { SWAP(H[s], H[f]); f = s; s <<= 1; } else break; } return ret; } };
然后来一个用正常C++翻译过来的浙大模板:
#define MAXN 10000 #define _cp(a,b) ((a)<(b)) typedef int elem_t; struct heap{ elem_t h[MAXN]; int n,p,c; void init(){n=0;} void ins(elem_t e){ for (p=++n;p>1&&_cp(e,h[p>>1]);h[p]=h[p>>1],p>>=1); h[p]=e; } //前面都看的懂吧就只加几个注释,不改了 //p = ++n: p是当前儿子节点,++n是堆的末尾位置 //p > 1:即p>>1 > 0,总不能超出堆的范围吧 //_cp(e, h[p>>1]:因为这个实现是替换父子元素,所以如果插入的地方比插入的元素大,就把重复的地方替换掉,结束 //h[p] = h[p>>1]:替换父子元素 //p >>= 1: 跳上去 //h[p] = e:插入的地方比插入的元素大,那么就替换掉重复的子节点,结束。 //具体还不清楚的画一条链模拟一下就清楚了 //实在不懂就看看这个硬式翻译的ins2吧 void ins2(elem_t e) { p = ++n; while(p > 1 && e < h[p>>1]) { h[p] = h[p>>1]; p >>= 1; } h[p] = e; } int del(elem_t& e){ if (!n) return 0; for (e=h[p=1],c=2;c<n&&_cp(h[c+=(c<n-1&&_cp(h[c+1],h[c]))],h[n]);h[p]=h[c],p=c,c<<=1); h[p]=h[n--];return 1; } int del2(elem_t& e) { if(!n) return 0; p = 1; c = 2; e = h[p]; while(c <= n-1) { if(c < n-1 && h[c+1] < h[c]) c++; if(h[c] >= h[n]) break; h[p] = h[c]; p = c; c <<= 1; } h[p] = h[n--]; return 1; } //我真不知道这个人类是如何把这么多代码缩到一个for里面去的,zyys };