大小堆操作

来源:互联网 发布:网络借贷监管暂行办法 编辑:程序博客网 时间:2024/06/16 19:27

大小堆的概念:
如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树 的顺序存储方式存储在一个一维数组中,并满足:Ki <= K2*i+1 且 Ki<= K2*i+2 (Ki >= K2*i+1 且 Ki >= K2*i+2) i = 0,1,2…,则称这个堆为最小堆(或最大 堆)。

最小堆:任一结点的关键码均小于等于它的左右孩子的关键码,位于堆顶结点的关键码最小
最大堆:任一结点的关键码均大于等于它的左右孩子的关键码,位于堆顶结点的关键码最大

对于堆主要的是堆的插入和删除引起的调整过程:
由于堆的插入和删除会引起堆不在符合大小堆的性质,从而引发调整;

大小堆的比较器:

template<typename T>//小堆比较器class Less{public: bool operator()(T& left, T& right) {  return left < right; }};template<typename T>//大堆比较器class High{public: bool operator()(T& left, T& right) {  return right>left; }};

模板:

template < class T,class Compera = Less<T>>

大小堆的创建过程:

Heap(const T array[], size_t size) //创建一个堆 {  _heap.resize(size);  //堆得大小一次性分配够了  for(size_t idx=0;idx<size;++idx)   {   //_heap.push_back(array[idx]);   _heap[idx]=array[idx];  //将数组里面的元素逐个拷贝进创建的堆中   cout<<_heap[idx]<<" ";  }  cout<<endl;  // 找倒数第一个非叶子结点  int root = (_heap.size()-2)>>1;  for (; root >= 0; root--)   _AdjustDown(root);  for(int i = 0; i<_heap.size(); i++)   cout<<_heap[i]<<" ";  cout<<endl; } protected: std::vector<T> _heap;};

由底向上调整

 void AdjustDown(int root)    //自底而上进行调整 {  root=((_heap.size()-2)>>1); //从倒数第一个非叶子节点开始  for (; root >= 0; root--)  {   _AdjustDown(root);  }  for(int i = 0; i<_heap.size(); i++)   cout<<_heap[i]<<" ";  cout<<endl; } void  _AdjustDown(int root)//自底而上进行调整 {  size_t child=root*2+1; //左孩子  size_t  size=_heap.size();  while(child < size)  //左孩子的大小是否小于堆的大小  {   if(child + 1 < size &&Compera()(_heap[child+1], _heap[child]))    //比较左右孩子大小    child+=1; //如果左孩子大于右孩子   if(Compera()(_heap[child], _heap[root]))   {    std::swap(_heap[root],_heap[child]);  //双亲结点大于孩子结点,交换两个结点多大的位置    root=child;    child=root*2+1;   }   else    return;  } }

有顶至下调整:

 void AdjustUp(size_t root)//自顶而下进行调整 {  for (int idx=0;idx<root;idx++)  {   _AdjustUp(idx);  }  for (int i=0;i<_heap.size();i++)  {   cout<<_heap[i]<<"  ";   }  cout<<endl; } void _AdjustUp(size_t parent) {  size_t child=_heap.size()-1;  parent=(child-1)>>1;  while (child != 0)  {   if (Compera()(_heap[child], _heap[parent]))   {    std::swap(_heap[parent], _heap[child]);    child = parent;    parent = (child - 1) / 2;   }   else    break;  } }

堆结点的插入:堆的插入每次都在已经建成的而最小堆的后面插入,但插入之后,有可能破坏了对的 结构,这时就需要对堆进行重新调整。

 void Insert(const T& data) //向已创建的堆中插入元素 {  size_t size = _heap.size()+1;  _heap.push_back(data);  AdjustUp(size); }

堆的删除:从堆中删除堆顶元素。移除堆顶元素之后,用堆的最后一个节点填补取 走的堆顶元素,并将堆的实际元素个数减1。但用最后一个元素取代堆顶元素之后有可 能破坏堆,因此需要将对自顶向下调整,使其满足最大或最小堆。

 void Remove()  //移除堆中的元素 {   assert(!_heap.empty());   size_t size = _heap.size();   std::swap(_heap[0], _heap[size - 1]);   _heap.pop_back();   _AdjustDown(size-1); }
原创粉丝点击