二叉堆
容易证明:
一棵高为h的完全二叉树有2^h 到 2^(h+1)-1个结点。
这就意味着,完全二叉树的高是[logN]
特点:
任意位置i:
左儿子在位置2i上,右儿子在位置2i+1上,父亲在i/2上
一个堆数据结构将由一个Comparable数组和一个代表当前堆的大小的整数组成:
优先队列的接口:
1 template <typename Comparable> 2 class BinaryHeap 3 { 4 public: 5 explicit BinaryHeap ( int capacity = 10 ); 6 explicit BinaryHeap ( const Vector<Comparable> & items); 7 8 bool isEmpty() const; 9 const Comparable & findMin() const; 10 11 void insert(const Comparable & x); 12 void deleteMin(); 13 void deleteMin(Coparable & minItem); 14 void makeEmpty(); 15 private: 16 int currentSize; 17 vector<Comparable> array; 18 void buildHeap(); 19 void percolateDown(int hole); 20 }
堆序的性质:如果想要找到一个最小点,最好是把最小值移动到堆的最上方,使用方法: 上滤
应用比如插入一个元素到堆中:
1 void insert(const Comparable & x) 2 { 3 if(currentSize == array.size()-1) 4 array.resize(array.size()*2); 5 6 int hole = ++currentSize; 7 8 for( ; hole > 1 && x < array[hole/2];hole /= 2) 9 array[hole] = array[hole/2]; 10 array[hole] = x; 11 }
想要删除一个堆结点,一般都是要把堆结点移动到最顶端,然后通过 下滤 方法删除:
1 void deletMin() 2 { 3 if(isEmpty()) 4 throw UnderflowException(); 5 6 array[1] = array[currentSize--]; 7 percolateDown(1); 8 } 9 void deleteMin(Comparable & minItem) 10 { 11 if(isEmpty()) 12 throw UnderflowException(); 13 minItem = array[1]; 14 array[1] = array[currentSize--]; 15 percolateDown(1); 16 } 17 void percolateDown(int hole) 18 { 19 int child; 20 Comparable tmp = array[hole]; 21 for( ; hole*2 <= currentSize;hole = child) 22 { 23 child = hole*2; 24 if(child != currentSize && array[child+1] < array[child]) 25 child++; 26 if(array[child] < tmp) 27 array[hole] = array[child]; 28 else 29 break; 30 } 31 array[hole] = tmp; 32 }
堆的其他操作:
decreaseKey(p,@):把p结点的元素减少到p-@
increaseKey (p,@):把p结点的元素增加到p+@
remove (p)一般都是先用decreaseKey(p,无限大),减少到最小,然后移动至堆顶端,用deleteMin方法删除。
buildHeap:构造堆原始集合
1 explicit BinaryHeap( const vector<Comparable> & items): array(item.size()+10),currentSize(items.size()) 2 { 3 for(int i=0;i<items.size();i++) 4 array[i+1] = items[i]; 5 buildHeap(); 6 } 7 void buildHeap() 8 { 9 for( int i = currentSize/2; i>0;i--) 10 percolateDown(i); 11 }