松鼠的窝 2018-02-12
话说新开的博客十分好用...
所以,我打算开一个坑,名曰【算法系列】。
什么意思——从名字泥应该就猜得出来。。。
废话不多说,进入正文~~
首先,堆是一颗棵二叉树。。
其次,堆是一棵完全二叉树。。
然后,设有一关系 P(Type X, Type Y)
则,堆的每个元素 Element
满足:
foreach Child ∈ Element.Childs do ASSERT( P(Element.value, Child.value) );
说的明白点,就是每个元素和它的儿子有特定得关系。。。(忽略错别字)
所以,利用堆の性质,我们可以在O(lg n)
的时间复杂度内做一些好的事情。。。
设v是堆里一点,则:
v*2 是 v的左儿子
v*2+1 是 v的右儿子
在实际操作中,我们常用位运算加速操作。
即:
inline int LEFT(int x) {return (x<<);} inline int RIGHT(int x) {return (x<<|);} inline int FATHER(int x) {return (x>>);}
heapnum = ; memset(heap, , sizeof(heap));
这是堆比较重要的一个函数。
Heapify(x) 维护以为根的字树保持堆的性质。
代码:
void Heapify(int x){ int largest; if(LEFT(x) <= heapnum && P(heap[x],heap[LEFT(x)])) largest = LEFT(x); else largest = x; if(RIGHT(x) <= heapnum && P(heap[largest], heap[RIGHT(x)])) largest = RIGHT(x); if(largest != x){ Exchange(heap[x], heap[largest]); Heapify(largest); } }
该函数的作用是把x元素改为y,且必须满足P(heap[x],y)
void HeapInc(int x,int y){ heap[x] = y; while (x > && P(heap[FATHER(i)], heap[x])) { Exchange(heap[x], heap[FATHER(x)]); x = FATHER(x); } }
不说了。。。上代码:
附注:这里假设P(x,y)表示x<y, 如果P(x,y)表示x>y那么请用INF代替-INF
void HeapAdd(int x){ heap[++heapnum] = -INF; HeapInc(heapnum, x); }
首先 --- 返回堆首元素(哈哈,这个不会写的话···)
int Top(){ assert(heapnum >= ); //assert(x)表示断言,如果x为false就停止程 return heap[]; }
其次 --- 删除堆首元素
void Pop(){ assert(heapnum >= ); Exchange(heap[], heap[heapnum--]); if(heapnum) Heapify(); }
最后 --- 结合上面两个
int Extract(){ int val = Top(); Pop(); return val; }
非空:
bool Empty(){ return heapnum == ; }
神马是类?你猜····
const int N = ; const int HEAPSIZE = N * ; template <class TElement = int, class Operator = less<int> > class BasicHeap{ private: TElement Plc; TElement heap[HEAPSIZE + ]; int heapnum; Operator P; inline int LEFT(int x){return x<<;} inline int RIGHT(int x){return x<<|;} inline int FATHER(int x){return x>>;} inline void Exchange(TElement & x, TElement & y){TElement t = x; x = y; y = t;} void Heapify(int x){ int largest; if(LEFT(x) <= heapnum && P(heap[x],heap[LEFT(x)])) largest = LEFT(x); else largest = x; if(RIGHT(x) <= heapnum && P(heap[largest], heap[RIGHT(x)])) largest = RIGHT(x); if(largest != x){ Exchange(heap[x], heap[largest]); Heapify(largest); } } inline void Assert(bool flg){ if(!flg){ abort(); } } public: BasicHeap(){ heapnum = ; P = Operator(); } void Inc(int x,int y){ heap[x] = y; while (x > && P(heap[FATHER(x)], heap[x])) { Exchange(heap[x], heap[FATHER(x)]); x = FATHER(x); } } void Add(int y){ heap[++heapnum] = y; int x = heapnum; while (x > && P(heap[FATHER(x)], heap[x])) { Exchange(heap[x], heap[FATHER(x)]); x = FATHER(x); } } int Top(){ Assert(heapnum >= ); return heap[]; } void Pop(){ Assert(heapnum >= ); Exchange(heap[], heap[heapnum--]); if(heapnum) Heapify(); } int Extract(){ int val = Top(); Pop(); return val; } void Clear(){ heapnum = ; } bool Empty(){ return heapnum == ; } }; typedef BasicHeap<> MaxHeap; typedef BasicHeap<int, greater<int> > MinHeap;