二项堆 Binomial Heap

来源: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;

}

猜你喜欢

转载自blog.csdn.net/qq_26043397/article/details/77933117
今日推荐