//
// main.cpp
// Data Structure TRY1
//
// Created by zr9558 on 6/7/13.
// Copyright (c) 2013 zr9558. All rights reserved.
//
// Data Structure C++, Weiss, P.246 Binomial queue
#include<iostream>
using namespace std;
#include<vector>
#include<math.h>
template<typename Comparable>
class BinomialQueue
{
public:
BinomialQueue();
BinomialQueue( const Comparable & item);
BinomialQueue( const BinomialQueue &rhs);
~BinomialQueue();
bool isEmpty() const;
const Comparable & findMin() const;
void insert( const Comparable &x);
void deleteMin();
void deleteMin( Comparable & minItem);
void makeEmpty();
void merge( BinomialQueue &rhs);
const BinomialQueue & operator=( const BinomialQueue &rhs);
private:
struct BinomialNode
{
Comparable element;
BinomialNode *leftChild;
BinomialNode *nextSibling;
BinomialNode( const Comparable & theElement, BinomialNode *lt=NULL, BinomialNode *rt=NULL)
:element(theElement), leftChild(lt),nextSibling(rt){}
};
enum { DEFAULT_TREES=1};
int currentSize; // Number of items in priority queue;
vector<BinomialNode *> theTrees; // An array of tree roots;
/* Find index of tree containing the smallest item in the priority queue.
The priority queue must not be empty.
Return the index of tree containing the smallest item.
*/
int findMinIndex() const
{
int i;
int minIndex;
for( i=0; theTrees[i]==NULL; ++i) ;
for( minIndex=i; i<theTrees.size(); ++i)
if( theTrees[i]!=NULL && theTrees[i]->element<theTrees[minIndex]->element)
minIndex=i;
return minIndex;
}
int capacity() const
{
int sum=0;
for( int i=0; i<theTrees.size(); ++i)
sum+=pow(2,i);
return sum;
}
// return the result of merging equal-sized t1 and t2;
BinomialNode * combineTrees( BinomialNode *t1, BinomialNode *t2)
{
if( t2->element<t1->element)
return combineTrees(t2,t1);
t2->nextSibling=t1->leftChild;
t1->leftChild=t2;
return t1;
}
void makeEmpty( BinomialNode *&t)
{
if( t==NULL) return;
makeEmpty(t->leftChild);
makeEmpty(t->nextSibling);
delete t;
}
BinomialNode * clone( BinomialNode *t) const
{
if( t==NULL) return NULL;
return new BinomialNode(t->element, clone(t->leftChild), clone(t->nextSibling));
}
};
template<typename Comparable>
const Comparable & BinomialQueue<Comparable>::findMin() const
{
return theTrees[findMinIndex()]->element;
}
template<typename Comparable>
void BinomialQueue<Comparable>::insert(const Comparable &x)
{
BinomialQueue temp(x);
merge(temp);
}
template<typename Comparable>
void BinomialQueue<Comparable>::makeEmpty()
{
for( int i=0; i!=theTrees.size(); ++i)
makeEmpty(theTrees[i]);
}
template<typename Comparable>
bool BinomialQueue<Comparable>::isEmpty() const
{
return currentSize==0;
}
template<typename Comparable>
BinomialQueue<Comparable>::BinomialQueue():currentSize(0)
{
for( int i=0; i!=DEFAULT_TREES; ++i)
theTrees.push_back(NULL);
}
template<typename Comparable>
BinomialQueue<Comparable>::BinomialQueue( const Comparable & item):currentSize(1)
{
theTrees.push_back(new BinomialNode(item));
}
template<typename Comparable>
BinomialQueue<Comparable>::BinomialQueue( const BinomialQueue &rhs):currentSize(rhs.currentSize)
{
for( int i=0; i!=rhs.theTrees.size(); ++i)
theTrees.push_back(clone(rhs.theTrees[i]));
}
template<typename Comparable>
BinomialQueue<Comparable>::~BinomialQueue()
{
makeEmpty();
}
template<typename Comparable>
const BinomialQueue<Comparable> & BinomialQueue<Comparable>::operator=(const BinomialQueue &rhs)
{
if( this!=&rhs)
{
makeEmpty();
theTrees.clear();
currentSize=rhs.currentSize;
for( int i=0; i!=rhs.theTrees.size(); ++i)
theTrees.push_back(clone(rhs.theTrees[i]));
}
return *this;
}
/*
Merge rhs into the priority queue.
rhs becomes empty. rhs must be different from this.
*/
template<typename Comparable>
void BinomialQueue<Comparable>::merge(BinomialQueue & rhs)
{
if( this==&rhs) return; // avoid aliasing problems
currentSize+=rhs.currentSize;
if( currentSize>capacity())
{
int oldNumTrees=int(theTrees.size());
int newNumTrees=max(int(theTrees.size()), int(rhs.theTrees.size()))+1;
theTrees.resize(newNumTrees);
for( int i=oldNumTrees; i<newNumTrees; ++i)
theTrees[i]=NULL;
}
BinomialNode *carry=NULL;
for( int i=0, j=1; j<=currentSize; i++,j*=2)
{
BinomialNode *t1=theTrees[i];
BinomialNode *t2=i<rhs.theTrees.size() ? rhs.theTrees[i]: NULL;
int whichCase= t1==NULL ? 0 : 1;
whichCase+= t2==NULL ? 0 : 2;
whichCase+= carry==NULL ? 0 : 4;
switch(whichCase)
{
case 0: // No trees;
case 1: // only this
break;
case 2: // only rhs
theTrees[i]=t2;
rhs.theTrees[i]=NULL;
break;
case 3: // this and rhs
carry=combineTrees(t1, t2);
theTrees[i]=rhs.theTrees[i]=NULL;
break;
case 4: // only carry
theTrees[i]=carry;
carry=NULL;
break;
case 5: // this and carry;
carry=combineTrees(t1, carry);
theTrees[i]=NULL;
break;
case 6: // rhs and carry
carry=combineTrees(t2, carry);
rhs.theTrees[i]=NULL;
break;
case 7: // all three
theTrees[i]=carry;
carry=combineTrees(t1, t2);
rhs.theTrees[i]=NULL;
break;
}
}
for( int i=0; i!=rhs.theTrees.size(); ++i)
rhs.theTrees[i]=NULL;
rhs.currentSize=0;
}
template<typename Comparable>
void BinomialQueue<Comparable>::deleteMin( Comparable & minItem)
{
int minIndex=findMinIndex();
minItem=theTrees[minIndex]->element;
BinomialNode *oldRoot=theTrees[minIndex];
BinomialNode *deletedTree=oldRoot->leftChild;
delete oldRoot;
// Construct H''
BinomialQueue deletedQueue;
deletedQueue.theTrees.resize(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=NULL;
}
// Construct H'
theTrees[minIndex]=NULL;
currentSize-=deletedQueue.currentSize+1;
merge(deletedQueue);
}
template<typename Comparable>
void BinomialQueue<Comparable>::deleteMin()
{
Comparable temp;
deleteMin(temp);
}
int main()
{
BinomialQueue<int> Q;
for( int i=0; i<20; ++i)
Q.insert(rand()%100);
BinomialQueue<int> Q1, Q2(Q);
Q1=Q;
while( !Q.isEmpty())
{
cout<<Q.findMin()<<" ";
Q.deleteMin();
}
cout<<endl;
while( !Q1.isEmpty())
{
cout<<Q1.findMin()<<" ";
Q1.deleteMin();
}
cout<<endl;
while( !Q2.isEmpty())
{
cout<<Q2.findMin()<<" ";
Q2.deleteMin();
}
cout<<endl;
return 0;
}