1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
|
template <typename Comparable>
class PriorityQueue
{
public:
PriorityQueue( ) : theTrees( DEFAULT_TREES )
{
for( auto & root : theTrees )
root = nullptr;
currentSize = 0;
}
PriorityQueue( const Comparable & item ) : theTrees( 1 ), currentSize{ 1 }
{ theTrees[ 0 ] = new BinomialNode{ item, nullptr, nullptr }; }
PriorityQueue( const PriorityQueue & rhs )
: theTrees( rhs.theTrees.size( ) ),currentSize{ rhs.currentSize }
{
for( int i = 0; i < rhs.theTrees.size( ); ++i )
theTrees[ i ] = clone( rhs.theTrees[ i ] );
}
PriorityQueue( PriorityQueue && rhs )
: theTrees{ std::move( rhs.theTrees ) }, currentSize{ rhs.currentSize }
{
}
/**
* Insert item x into the priority queue; allows duplicates.
*/
void insert( const Comparable & x )
{
PriorityQueue oneItem{ x }; merge( oneItem );
}
/**
* Insert item x into the priority queue; allows duplicates.
*/
void insert( Comparable && x )
{
PriorityQueue oneItem{ std::move( x ) }; merge( oneItem );
}
void merge( PriorityQueue & rhs )
{
if( this == &rhs ) // Avoid aliasing problems
return;
currentSize += rhs.currentSize;
if( currentSize > 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;
switch( whichCase )
{
case 0: /* No trees */
case 1: /* Only this */
break;
case 2: /* Only rhs */
theTrees[ i ] = t2;
rhs.theTrees[ i ] = nullptr;
break;
case 4: /* Only carry */
theTrees[ i ] = carry;
carry = nullptr;
break;
case 3: /* this and rhs */
carry = combineTrees( t1, t2 );
theTrees[ i ] = rhs.theTrees[ i ] = nullptr;
break;
case 5: /* this and carry */
carry = combineTrees( t1, carry );
theTrees[ i ] = nullptr;
break;
case 6: /* rhs and carry */
carry = combineTrees( t2, carry );
rhs.theTrees[ i ] = nullptr;
break;
case 7: /* All three */
theTrees[ i ] = carry;
carry = combineTrees( t1, t2 );
rhs.theTrees[ i ] = nullptr;
break;
}
}
for( auto & root : rhs.theTrees )
root = nullptr;
rhs.currentSize = 0;
}
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;
vector<BinomialNode *> theTrees; // An array of tree roots
int currentSize; // Number of items in the priority queue
// Trouble with the pointer to BinomialNode declaration for the unordered_map
unordered_map<Comparable , >hashTable;
|