📄 pairingheap.cpp
字号:
/** * \brief Pairing heap datastructure implementation * * Based on example code in "Data structures and Algorithm Analysis in C++" * by Mark Allen Weiss, used and released under the LGPL by permission * of the author. * * No promises about correctness. Use at your own risk! * * Authors: * Mark Allen Weiss * Tim Dwyer <tgdwyer@gmail.com> * * Copyright (C) 2005 Authors * * This version is released under the CPL (Common Public License) with * the Graphviz distribution. * A version is also available under the LGPL as part of the Adaptagrams * project: http://sourceforge.net/projects/adaptagrams. * If you make improvements or bug fixes to this code it would be much * appreciated if you could also contribute those changes back to the * Adaptagrams repository. */#include <vector>#include <list>#include "dsexceptions.h"#include "PairingHeap.h"#ifndef PAIRING_HEAP_CPP#define PAIRING_HEAP_CPPusing namespace std;/*** Construct the pairing heap.*/template <class T>PairingHeap<T>::PairingHeap( bool (*lessThan)(T const &lhs, T const &rhs) ){ root = NULL; counter=0; this->lessThan=lessThan;}/*** Copy constructor*/template <class T>PairingHeap<T>::PairingHeap( const PairingHeap<T> & rhs ){ root = NULL; counter=rhs->size(); *this = rhs;}/*** Destroy the leftist heap.*/template <class T>PairingHeap<T>::~PairingHeap( ){ makeEmpty( );}/*** Insert item x into the priority queue, maintaining heap order.* Return a pointer to the node containing the new item.*/template <class T>PairNode<T> *PairingHeap<T>::insert( const T & x ){ PairNode<T> *newNode = new PairNode<T>( x ); if( root == NULL ) root = newNode; else compareAndLink( root, newNode ); counter++; return newNode;}template <class T>int PairingHeap<T>::size() { return counter;}/*** Find the smallest item in the priority queue.* Return the smallest item, or throw Underflow if empty.*/template <class T>const T & PairingHeap<T>::findMin( ) const{ if( isEmpty( ) ) throw Underflow( ); return root->element;}/** * Remove the smallest item from the priority queue. * Throws Underflow if empty. */template <class T>void PairingHeap<T>::deleteMin( ){ if( isEmpty( ) ) throw Underflow( ); PairNode<T> *oldRoot = root; if( root->leftChild == NULL ) root = NULL; else root = combineSiblings( root->leftChild ); counter--; delete oldRoot;}/*** Test if the priority queue is logically empty.* Returns true if empty, false otherwise.*/template <class T>bool PairingHeap<T>::isEmpty( ) const{ return root == NULL;}/*** Test if the priority queue is logically full.* Returns false in this implementation.*/template <class T>bool PairingHeap<T>::isFull( ) const{ return false;}/*** Make the priority queue logically empty.*/template <class T>void PairingHeap<T>::makeEmpty( ){ reclaimMemory( root ); root = NULL;}/*** Deep copy.*/template <class T>const PairingHeap<T> &PairingHeap<T>::operator=( const PairingHeap<T> & rhs ){ if( this != &rhs ) { makeEmpty( ); root = clone( rhs.root ); } return *this;}/*** Internal method to make the tree empty.* WARNING: This is prone to running out of stack space.*/template <class T>void PairingHeap<T>::reclaimMemory( PairNode<T> * t ) const{ if( t != NULL ) { reclaimMemory( t->leftChild ); reclaimMemory( t->nextSibling ); delete t; }}/*** Change the value of the item stored in the pairing heap.* Does nothing if newVal is larger than currently stored value.* p points to a node returned by insert.* newVal is the new value, which must be smaller* than the currently stored value.*/template <class T>void PairingHeap<T>::decreaseKey( PairNode<T> *p, const T & newVal ){ if( p->element < newVal ) return; // newVal cannot be bigger p->element = newVal; if( p != root ) { if( p->nextSibling != NULL ) p->nextSibling->prev = p->prev; if( p->prev->leftChild == p ) p->prev->leftChild = p->nextSibling; else p->prev->nextSibling = p->nextSibling; p->nextSibling = NULL; compareAndLink( root, p ); }}/*** Internal method that is the basic operation to maintain order.* Links first and second together to satisfy heap order.* first is root of tree 1, which may not be NULL.* first->nextSibling MUST be NULL on entry.* second is root of tree 2, which may be NULL.* first becomes the result of the tree merge.*/template <class T>void PairingHeap<T>::compareAndLink( PairNode<T> * & first, PairNode<T> *second ) const{ if( second == NULL ) return; if( lessThan(second->element,first->element) ) { // Attach first as leftmost child of second second->prev = first->prev; first->prev = second; first->nextSibling = second->leftChild; if( first->nextSibling != NULL ) first->nextSibling->prev = first; second->leftChild = first; first = second; } else { // Attach second as leftmost child of first second->prev = first; first->nextSibling = second->nextSibling; if( first->nextSibling != NULL ) first->nextSibling->prev = first; second->nextSibling = first->leftChild; if( second->nextSibling != NULL ) second->nextSibling->prev = second; first->leftChild = second; }}/*** Internal method that implements two-pass merging.* firstSibling the root of the conglomerate;* assumed not NULL.*/template <class T>PairNode<T> *PairingHeap<T>::combineSiblings( PairNode<T> *firstSibling ) const{ if( firstSibling->nextSibling == NULL ) return firstSibling; // Allocate the array static vector<PairNode<T> *> treeArray( 5 ); // Store the subtrees in an array int numSiblings = 0; for( ; firstSibling != NULL; numSiblings++ ) { if( numSiblings == (int)treeArray.size( ) ) treeArray.resize( numSiblings * 2 ); treeArray[ numSiblings ] = firstSibling; firstSibling->prev->nextSibling = NULL; // break links firstSibling = firstSibling->nextSibling; } if( numSiblings == (int)treeArray.size( ) ) treeArray.resize( numSiblings + 1 ); treeArray[ numSiblings ] = NULL; // Combine subtrees two at a time, going left to right int i = 0; for( ; i + 1 < numSiblings; i += 2 ) compareAndLink( treeArray[ i ], treeArray[ i + 1 ] ); int j = i - 2; // j has the result of last compareAndLink. // If an odd number of trees, get the last one. if( j == numSiblings - 3 ) compareAndLink( treeArray[ j ], treeArray[ j + 2 ] ); // Now go right to left, merging last tree with // next to last. The result becomes the new last. for( ; j >= 2; j -= 2 ) compareAndLink( treeArray[ j - 2 ], treeArray[ j ] ); return treeArray[ 0 ];}/*** Internal method to clone subtree.* WARNING: This is prone to running out of stack space.*/template <class T>PairNode<T> *PairingHeap<T>::clone( PairNode<T> * t ) const{ if( t == NULL ) return NULL; else { PairNode<T> *p = new PairNode<T>( t->element ); if( ( p->leftChild = clone( t->leftChild ) ) != NULL ) p->leftChild->prev = p; if( ( p->nextSibling = clone( t->nextSibling ) ) != NULL ) p->nextSibling->prev = p; return p; }}template <class T>ostream& operator <<(ostream &os, const PairingHeap<T> &b){ os<<"Heap:"; if (b.root != NULL) { PairNode<T> *r = b.root; list<PairNode<T>*> q; q.push_back(r); while (!q.empty()) { r = q.front(); q.pop_front(); if (r->leftChild != NULL) { os << *r->element << ">"; PairNode<T> *c = r->leftChild; while (c != NULL) { q.push_back(c); os << "," << *c->element; c = c->nextSibling; } os << "|"; } } } return os;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -