2
* \brief Pairing heap datastructure implementation
4
* Based on example code in "Data structures and Algorithm Analysis in C++"
5
* by Mark Allen Weiss, used and released under the LGPL by permission
8
* No promises about correctness. Use at your own risk!
12
* Tim Dwyer <tgdwyer@gmail.com>
14
* Copyright (C) 2005 Authors
16
* Released under GNU LGPL. Read the file 'COPYING' for more information.
21
#include "dsexceptions.h"
22
#include "PairingHeap.h"
24
#ifndef PAIRING_HEAP_CPP
25
#define PAIRING_HEAP_CPP
28
* Construct the pairing heap.
31
PairingHeap<T>::PairingHeap( bool (*lessThan)(T const &lhs, T const &rhs) )
35
this->lessThan=lessThan;
43
PairingHeap<T>::PairingHeap( const PairingHeap<T> & rhs )
51
* Destroy the leftist heap.
54
PairingHeap<T>::~PairingHeap( )
60
* Insert item x into the priority queue, maintaining heap order.
61
* Return a pointer to the node containing the new item.
65
PairingHeap<T>::insert( const T & x )
67
PairNode<T> *newNode = new PairNode<T>( x );
72
compareAndLink( root, newNode );
77
int PairingHeap<T>::size() {
81
* Find the smallest item in the priority queue.
82
* Return the smallest item, or throw Underflow if empty.
85
const T & PairingHeap<T>::findMin( ) const
92
* Remove the smallest item from the priority queue.
93
* Throws Underflow if empty.
96
void PairingHeap<T>::deleteMin( )
101
PairNode<T> *oldRoot = root;
103
if( root->leftChild == NULL )
106
root = combineSiblings( root->leftChild );
112
* Test if the priority queue is logically empty.
113
* Returns true if empty, false otherwise.
116
bool PairingHeap<T>::isEmpty( ) const
122
* Test if the priority queue is logically full.
123
* Returns false in this implementation.
126
bool PairingHeap<T>::isFull( ) const
132
* Make the priority queue logically empty.
135
void PairingHeap<T>::makeEmpty( )
137
reclaimMemory( root );
145
const PairingHeap<T> &
146
PairingHeap<T>::operator=( const PairingHeap<T> & rhs )
151
root = clone( rhs.root );
158
* Internal method to make the tree empty.
159
* WARNING: This is prone to running out of stack space.
162
void PairingHeap<T>::reclaimMemory( PairNode<T> * t ) const
166
reclaimMemory( t->leftChild );
167
reclaimMemory( t->nextSibling );
173
* Change the value of the item stored in the pairing heap.
174
* Does nothing if newVal is larger than currently stored value.
175
* p points to a node returned by insert.
176
* newVal is the new value, which must be smaller
177
* than the currently stored value.
180
void PairingHeap<T>::decreaseKey( PairNode<T> *p,
183
if( lessThan(p->element,newVal) )
184
return; // newVal cannot be bigger
188
if( p->nextSibling != NULL )
189
p->nextSibling->prev = p->prev;
190
if( p->prev->leftChild == p )
191
p->prev->leftChild = p->nextSibling;
193
p->prev->nextSibling = p->nextSibling;
195
p->nextSibling = NULL;
196
compareAndLink( root, p );
201
* Internal method that is the basic operation to maintain order.
202
* Links first and second together to satisfy heap order.
203
* first is root of tree 1, which may not be NULL.
204
* first->nextSibling MUST be NULL on entry.
205
* second is root of tree 2, which may be NULL.
206
* first becomes the result of the tree merge.
209
void PairingHeap<T>::
210
compareAndLink( PairNode<T> * & first,
211
PairNode<T> *second ) const
215
if( lessThan(second->element,first->element) )
217
// Attach first as leftmost child of second
218
second->prev = first->prev;
219
first->prev = second;
220
first->nextSibling = second->leftChild;
221
if( first->nextSibling != NULL )
222
first->nextSibling->prev = first;
223
second->leftChild = first;
228
// Attach second as leftmost child of first
229
second->prev = first;
230
first->nextSibling = second->nextSibling;
231
if( first->nextSibling != NULL )
232
first->nextSibling->prev = first;
233
second->nextSibling = first->leftChild;
234
if( second->nextSibling != NULL )
235
second->nextSibling->prev = second;
236
first->leftChild = second;
241
* Internal method that implements two-pass merging.
242
* firstSibling the root of the conglomerate;
247
PairingHeap<T>::combineSiblings( PairNode<T> *firstSibling ) const
249
if( firstSibling->nextSibling == NULL )
252
// Allocate the array
253
static vector<PairNode<T> *> treeArray( 5 );
255
// Store the subtrees in an array
257
for( ; firstSibling != NULL; numSiblings++ )
259
if( numSiblings == (int)treeArray.size( ) )
260
treeArray.resize( numSiblings * 2 );
261
treeArray[ numSiblings ] = firstSibling;
262
firstSibling->prev->nextSibling = NULL; // break links
263
firstSibling = firstSibling->nextSibling;
265
if( numSiblings == (int)treeArray.size( ) )
266
treeArray.resize( numSiblings + 1 );
267
treeArray[ numSiblings ] = NULL;
269
// Combine subtrees two at a time, going left to right
271
for( ; i + 1 < numSiblings; i += 2 )
272
compareAndLink( treeArray[ i ], treeArray[ i + 1 ] );
276
// j has the result of last compareAndLink.
277
// If an odd number of trees, get the last one.
278
if( j == numSiblings - 3 )
279
compareAndLink( treeArray[ j ], treeArray[ j + 2 ] );
281
// Now go right to left, merging last tree with
282
// next to last. The result becomes the new last.
283
for( ; j >= 2; j -= 2 )
284
compareAndLink( treeArray[ j - 2 ], treeArray[ j ] );
285
return treeArray[ 0 ];
289
* Internal method to clone subtree.
290
* WARNING: This is prone to running out of stack space.
294
PairingHeap<T>::clone( PairNode<T> * t ) const
300
PairNode<T> *p = new PairNode<T>( t->element );
301
if( ( p->leftChild = clone( t->leftChild ) ) != NULL )
302
p->leftChild->prev = p;
303
if( ( p->nextSibling = clone( t->nextSibling ) ) != NULL )
304
p->nextSibling->prev = p;
309
ostream& operator <<(ostream &os, const PairingHeap<T> &b)
312
if (b.root != NULL) {
313
PairNode<T> *r = b.root;
314
list<PairNode<T>*> q;
319
if (r->leftChild != NULL) {
320
os << *r->element << ">";
321
PairNode<T> *c = r->leftChild;
324
os << "," << *c->element;