堆——二项队列
来源:互联网 发布:网络安全管理心得 编辑:程序博客网 时间:2024/05/21 21:42
二项队列由一系列二项树组成,每个高度只允许一棵二项树。每棵树Bk由一个根和Bk-1…B0组成。删除最小值操作是先找到最小根值的树,然后删掉树根,得到新的一组二项队列Bk-1…B0。将两个队列合并,便完成了删除最小值操作。
#include <vector>template <typename Comparable>class BinomialQueue{public: BinomialQueue(); BinomialQueue(const Comparable & item); BinomialQueue(const BinomialQueue & rhs); BinomialQueue(BinomialQueue && rhs); ~BinomialQueue(); BinomialQueue & operator=(const BinomialQueue & rhs); BinomialQueue & operator=(BinomialQueue && rhs); bool isEmpty()const; const Comparable & findMin()const; void insert(const Comparable & x); void insert(Comparable && x); void deleteMin(); void deleteMin(Comparable & minItem); void makeEmpty(); void merge(BinomialQueue & rhs);private: struct BinomialNode { Comparable element; BinomialNode *leftChild; BinomialNode *nextSibling; BinomialNode(const Comparable & e,BinomialNode * lt,BinomialNode *rt) :element(e),leftChild(lt),nextSibling(rt){} BinomialNode(Comparable && e,BinomialNode * lt,BinomialNode *rt) :element(std::move(e)),leftChild(lt),nextSibling(rt){} }; const static int DEFAULT_TREES=1; std::vector<BinomialNode *> theTrees; int currentSize; //优先队列中的项数 int findMinIndex()const; int capacity()const //数组最多能存储的项数 { int Num=0; int s=1; for(int i=0;i<theTrees.size();++i) { Num+=s; s*=2; } return Num; } BinomialNode * combineTrees(BinomialNode *t1,BinomialNode *t2); void makeEmpty(BinomialNode * & t); BinomialNode * clone(BinomialNode * t)const;};//合并同样大小的二项树template <typename Comparable>typename BinomialQueue<Comparable>::BinomialNode *BinomialQueue<Comparable>::combineTrees(BinomialNode *t1, BinomialNode *t2){ if(t2->element<t1->element) return combineTrees(t2, t1); t2->nextSibling=t1->leftChild; t1->leftChild=t2; return t1;}template <typename Comparable>void BinomialQueue<Comparable>::merge(BinomialQueue & rhs){ if(this==&rhs) return; currentSize+=rhs.currentSize; if(currentSize>capacity()) //capacity代表当前数组能容纳的最多项数 { int oldNumTrees=theTrees.size(); int newNumTrees=max(theTrees.size(),rhs.theTrees.size())+1; theTrees.resize(newNumTrees); for(int i=oldNumTrees;i<newNumTrees;++i) theTrees[i]=nullptr; } BinomialNode *carry=nullptr; //由上一位合并而来的 for(int i=0,j=1;j<=currentSize;++i,j*=2) { BinomialNode *t1=theTrees[i]; BinomialNode *t2=i<rhs.theTrees.size()?rhs.theTrees[i]:nullptr; int whichcase=t1==nullptr?0:1; whichcase+=t2==nullptr?0:2; whichcase+=carry==nullptr?0:4; //类似加法,carry代表进位 switch (whichcase) { case 0: //都是空 case 1: //只有this break; case 2: //只有rhs theTrees[i]=t2; rhs.theTrees[i]=nullptr; break; case 4: //只有carry theTrees[i]=carry; carry=nullptr; break; case 3: //this和rhs carry=combineTrees(t1, t2); theTrees[i]=rhs.theTrees[i]=nullptr; break; case 5: //this和carry carry=combineTrees(t1, carry); theTrees[i]=nullptr; break; case 6: //carry和rhs carry=combineTrees(carry, t2); rhs.theTrees[i]=nullptr; break; case 7: //三者都有 theTrees[i]=carry; carry=combineTrees(carry, t2); rhs.theTrees[i]=nullptr; break; default: break; } } for(auto & root:rhs.theTrees) root=nullptr; rhs.currentSize=0;}template <typename Comparable>int BinomialQueue<Comparable>::findMinIndex()const{ int minIndex; int i; for(int i=0;theTrees[i]==nullptr;++i) ; for(minIndex=i;i<theTrees.size();++i) if(theTrees[i]!=nullptr&&theTrees[i]->element<theTrees[minIndex]->element) { minIndex=i; } return minIndex;}template <typename Comparable>void BinomialQueue<Comparable>::deleteMin(Comparable & minItem){ //if(isEmpty()) //throw UnderflowException{}; int minIndex=findMinIndex(); minItem=theTrees[minIndex]->element; BinomialNode *oldRoot=theTrees[minIndex]; BinomialNode *deletedTree=oldRoot->leftChild; delete oldRoot; BinomialQueue deletedQueue; deletedQueue.theTrees.resize(minIndex+1); //应该有minIndex个二项树 //将1左移minIndex位得到minIndex处项数然后减去1(根节点) deletedQueue.currentSize=(1<<minIndex)-1; for(int j=minIndex-1;j>=0;--j) { deletedQueue.theTrees[j]=deletedTree; deletedTree=deletedTree->nextSibling; deletedQueue.theTrees[j]->nextSibling=nullptr; } theTrees[minIndex]=nullptr; //因为将minIndex处删除掉了,所以currentSize要减去它的项数 currentSize-=deletedQueue.currentSize+1; merge(deletedQueue);}
阅读全文
0 0
- 堆——二项队列
- 堆与堆排序—优先队列
- 堆——优先队列
- heap的一些实现,二叉堆,左式堆,二项队列
- STL源码笔记(15)—堆和优先级队列(二)
- 优先队列(堆)——二叉堆的实现
- 优先队列——二项队列(binominal queue)
- 堆排序2——优先级队列
- 优先队列——二叉堆实现
- 优先队列——斜堆
- 数据结构——优先队列(堆)
- 堆的应用——优先级队列
- 堆的应用——优先级队列
- 优先队列——二叉堆、d堆、左式堆、斜堆
- C++实现优先队列——最小堆,d路堆及配对堆
- 优先队列——斐波那契堆
- 堆——神奇的优先队列(下)
- 堆——神奇的优先队列(上)
- 设计模式
- MySQL 数据库高负载故障分析
- Android常用工具类之获取屏幕相关的辅助类
- 浏览器内核
- 乐视股东大会变讨债大会 讨债者高喊乐视还钱
- 堆——二项队列
- Centos7安装go语言环境
- 反转数组中某一段
- KKT条件的推导
- mysql重启之后
- HDU2004 成绩转换
- UOJ220,NOI2016网格
- 面对对象编程第四节
- android widget