二项队列 C++实现
2016-05-08 10:30
363 查看
二项队列是比左式堆与斜堆更好的选择。
二项队列不是一棵树,是由堆序的集合组成的,成为森林。堆序中每一颗树都有约束,都为二项树,每一个高度只有一个二项树,每层的高度由两个下一层高度的树组成。B1= B0 + B0。
二项队列的合并是相同高度的二项树合并,并且insert与deleteMin都是依靠合并这个操作实现的。
template<typename T> class BinomialQueue { public: BinomialQueue(); BinomialQueue(const T &t); BinomialQueue(const BinomialQueue &rhs); ~BinomialQueue(); bool isEmpty() const; const T & findMin() const; void insert(const T &t); void deleteMin(); void deleteMin(T & t); void makeEmpty(); void merge(BinomialQueue & rhs); const BinomialQueue & operator= (const BinomialQueue &rhs); private: struct BinomialNode { T element; BinomialNode * leftChild; BinomialNode * nextSibling; BinomialNode(const T & t, BinomialNode * lc, BinomialNode *ns) : element(t), leftChild(lc), nextSibling(ns) {} }; enum { DEFAULT_TREES = 1}; int currentSize; vector<BinomialNode *> theTrees; int findMinIndex() const; int capacity() const; BinomialNode * combineTrees(BinomialNode * t1, BinomialNode * t2); void makeEmpty(BinomialNode * & t); BinomialNode * clone(BinomialNode * t) const; }; template<typename T> BinomialNode * BinomialQueue<T>::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 T> void BinomialQueue<T>::merge(BinomialQueue & rhs) { if (this == &rhs) return; currentSize == rhs.currentSize > theTrees.size() ? rhs.currentSize + 1 : theTrees.size() + 1; //上一层树合并生成的下一层树,没有则为空 BinomialNode * carry = nullptr; //书上写的这个j是什么意思啊? 求解 for (int i = 0, j = 1; i < 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; switch (whichCase) { case 0://没有树 case 1://就有本身这棵树 break; case 2://只有rhs有 theTrees[2] = t2; rhs.theTrees[2] = nullptr; break; case 4://只有carry theTrees[i] = carry; carry = nullptr; break; case 3://有本身和rhs carry = combineTrees(t1, t2); theTrees[i] = rhs.theTrees[i] = nullptr; break; case 5://本身和carry carry = combineTrees(t1, carry); theTrees[i] = nullptr; break; case 6://rhs与carry carry = combineTrees(t2, carry); rhs.theTrees[i] = nullptr; break; case 7://本身、rhs、carry都有 theTrees[i] = carry; carry = combineTrees(t1, t2); rhs.theTrees[i] = nullptr; break; } } for (int k = 0; k < rhs.theTrees.size(); ++k) rhs.theTrees[k] = nullptr; rhs.currentSize = 0; }
相关文章推荐
- 使用NDK c++建立一个Android应用
- Implement Trie (Prefix Tree)
- 【C++】Digest of 《effective C++》--1
- C语言函数sscanf()的用法
- C语言:关注EOF
- C语言函数fseek, fread, ftell的使用
- C++实验5-数组的分离
- C++ explicit关键字
- c++实验5-数组分离
- C++虚函数
- C++类的静态成员& 赋值vs初始化
- C语言内存的初始化
- C++对象链表的创建与销毁
- 从遗忘到捡起FFT信号处理
- Leetcode 206. Reverse Linked List cpp实现
- 一个简单的飞机订票系统
- C++指针与const
- 用gdb调试C与C++程序
- 将两个非递减的有序链表合并为一个非递增的有序链表(C语言编程实现)
- 将两个递增的有序链表合并为一个递增的有序链表(C语言编程实现)