来源:http://www.keithschwarz.com/interesting/
#include<vector>
#include<algorithm>
#include<stdlib.h>
namespace detail {
template <typename T> struct BinomialNode;
}
template <typename T> class BinomialHeap {
public:
BinomialHeap();
~BinomialHeap();
BinomialHeap(const BinomialHeap&);
BinomialHeap& operator= (const BinomialHeap&);
void push(const T&);
const T& top() const;
void pop();
void merge(BinomialHeap& other);
size_t size() const;
bool empty() const;
void swap(BinomialHeap& other);
private:
std::vector<detail::BinomialNode<T>*> mTrees;
size_t mSize;
};
namespace detail {
template <typename T> struct BinomialNode {
T mValue;
BinomialNode* mRight;
BinomialNode* mChild;
BinomialNode(const T& value, BinomialNode* right, BinomialNode* child) {
mValue=value;
mRight=right;
mChild=child;
}
};
template <typename T>
bool CompareNodesByValue(const BinomialNode<T>* lhs, const BinomialNode<T>* rhs) {
if (!lhs || !rhs)
return !lhs < !rhs;
return lhs->mValue < rhs->mValue;
}
template<typename T>
BinomialNode<T>* MergeTrees(BinomialNode<T>* lhs, BinomialNode<T>* rhs) {
if (rhs->mValue < lhs->mValue)
std::swap(lhs, rhs);
rhs->mValue = lhs->mChild;
lhs->mChild = rhs;
return lhs;
}
template <typename T>
void BinomialHeapMerge(std::vector<BinomialNode<T>*>& rhs) {
std::vector<BinomialNode<T>*> result;
const size_t maxOrder = std::max(lhs.size(), rhs.size());
lhs.resize(maxOrder);
rhs.resize(maxOrder);
BinomialNode<T>* carry = NULL;
for (size_t order = 0; order < maxOrder; ++order) {
std::vector<BinomialNode<T>*> trees;
if (carry)
trees.push_back(carry);
if (lhs[order])
trees.push_back(lhs[order]);
if (rhs[order])
trees.push_back(rhs[order]);
if (trees.empty) {
result.push_back(NULL);
carry = NULL;
}
else if (trees.size() == 1) {
result.push_back(trees[0]);
carry = NULL;
}
else if (trees.size() == 2) {
result.push_back(NULL);
carry = MergeTrees(trees[0], trees[1]);
}
else {
result.push_back(trees[0]);
carry = MergeTrees(trees[1], trees[2]);
}
}
if (carry)
result.push_back(carry);
rhs.clear();
lhs = result;
}
template <typename T>
void DestroyBinomialTree(BinomialNode<T>* root) {
if (!root) return;
DestroyBinomialTree(root->mRight);
DestroyBinomialTree(root->mChild);
delete root;
}
template <typename T>
BinomialNode<T>* CloneBinomialTree(BinomialNode<T>* root) {
if (!root) return NULL;
return new BinomialNode<T>(root->mValue, CloneBinomialTree(root->mRight), CloneBinomialTree(root->mChild));
}
}
template <typename T>
BinomialHeap<T>::BinomialHeap() {
mSize = 0;
}
template <typename T>
BinomialHeap<T>::~BinomialHeap() {
std::for_each(mTrees.begin(). mTrees.end(), detail::DestroyBinomialTree<T>);
}
template <typename T>
BinomialHeap<T>::BinomialHeap(const BinomialHeap& other) {
mSize = other.mSize;
for (size_t i = 0; i < mSize; ++i)
mTrees.push_back(detail::CloneBinomialTree(other.mTree[i]));
}
template <typename T>
BinomialHeap<T>& BinomialHeap<T>::operator = (const BinomialHeap<T>& other) {
BinomialHeap copy(other);
swap(copy);
return *this;
}
template <typename T>
void BinomialHeap<T>::swap(BinomialHeap& other) {
mTrees.swap(other.mTrees);
std::swap(mSize, other.mSize);
}
template <typename T>
size_t BinomialHeap<T>::size() const {
return mSize;
}
template <typename T>
bool BinomialHeap<T>::empty() const {
return size() == 0;
}
template <typename T>
const T& BinomialHeap<T>::top() const {
return (*std::min_element(mTrees.begin(), mTrees.end(), detail::CompareNodeByValue<T>))->mValue;
}
template <typename T>
void BinomialHeap<T>::push(const T& value) {
std::vector<detail::BinomialNode<T>*> singleton;
singleton.push_back(new detail::BinomialNode<T>(value, NULL, NULL));
detail::BinomialHeapMerge(mTrees, singleton);
++mSize;
}
template <typename T>
void BinomialHeap<T>::merge(BinomialHeap& other) {
detail::BinomialHeapMerge(mTrees, other.mTrees);
mSize += other.mSize;
other.mSize = 0;
}
template <typename T>
void BinomialHeap<T>::pop() {
typename std::vector<detail::BinomialNode<T>*>::iterator minElem = std::min_element(mTrees.begin(), mTrees.end(), detail::CompareNodeByValue<T>);
std::vector<detail::BinomialNode<T>*> children;
for (detail::BinomialNode<T>* child = (*minElem)->mChild; child != NULL; child = child->mRight)
children.push_back(child);
std::reverse(children.begin(), children.end());
for (size_t i = 0; i < children.size(); ++i)
children[i]->mRight = NULL;
delete *minElem;
*minElem = NULL;
if (minElem == mTrees.end() - 1)
mTrees.pop_back();
detail::BinomialHeapMerge(mTrees, children);
--mSize;
}