• 数据结构-二项队列


    实现:

      1 #ifndef BINOMIAL_QUEUE_H
      2 #define BINOMIAL_QUEUE_H
      3 
      4 #include <iostream>
      5 #include <vector>
      6 #include "dsexceptions.h"
      7 using namespace std;
      8 
      9 // Binomial queue class
     10 //
     11 // CONSTRUCTION: with no parameters
     12 //
     13 // ******************PUBLIC OPERATIONS*********************
     14 // void insert( x )       --> Insert x
     15 // deleteMin( )           --> Return and remove smallest item
     16 // Comparable findMin( )  --> Return smallest item
     17 // bool isEmpty( )        --> Return true if empty; else false
     18 // void makeEmpty( )      --> Remove all items
     19 // void merge( rhs )      --> Absorb rhs into this heap
     20 // ******************ERRORS********************************
     21 // Throws UnderflowException as warranted
     22 
     23 template <typename Comparable>
     24 class BinomialQueue
     25 {
     26   public:
     27     BinomialQueue( ) : theTrees( DEFAULT_TREES )
     28     {
     29         for( auto & root : theTrees )
     30             root = nullptr;
     31         currentSize = 0;
     32     }
     33 
     34     BinomialQueue( const Comparable & item ) : theTrees( 1 ), currentSize{ 1 }
     35       { theTrees[ 0 ] = new BinomialNode{ item, nullptr, nullptr }; }
     36 
     37     BinomialQueue( const BinomialQueue & rhs )
     38       : theTrees( rhs.theTrees.size( ) ),currentSize{ rhs.currentSize }
     39     { 
     40         for( int i = 0; i < rhs.theTrees.size( ); ++i )
     41             theTrees[ i ] = clone( rhs.theTrees[ i ] );
     42     }
     43 
     44     BinomialQueue( BinomialQueue && rhs )
     45       : theTrees{ std::move( rhs.theTrees ) }, currentSize{ rhs.currentSize }
     46     { 
     47     }
     48 
     49     ~BinomialQueue( )
     50       { makeEmpty( ); }
     51 
     52     
     53     /**
     54      * Deep copy.
     55      */
     56     BinomialQueue & operator=( const BinomialQueue & rhs )
     57     {
     58         BinomialQueue copy = rhs;
     59         std::swap( *this, copy );
     60         return *this;
     61     }
     62         
     63     /**
     64      * Move.
     65      */
     66     BinomialQueue & operator=( BinomialQueue && rhs )
     67     {
     68         std::swap( currentSize, rhs.currentSize );
     69         std::swap( theTrees, rhs.theTrees );
     70         
     71         return *this;
     72     }
     73     
     74     /**
     75      * Return true if empty; false otherwise.
     76      */
     77     bool isEmpty( ) const
     78       { return currentSize == 0; }
     79 
     80     /**
     81      * Returns minimum item.
     82      * Throws UnderflowException if empty.
     83      */
     84     const Comparable & findMin( ) const
     85     {
     86         if( isEmpty( ) )
     87             throw UnderflowException{ };
     88 
     89         return theTrees[ findMinIndex( ) ]->element;
     90     }
     91     
     92     /**
     93      * Insert item x into the priority queue; allows duplicates.
     94      */
     95     void insert( const Comparable & x )
     96       { BinomialQueue oneItem{ x }; merge( oneItem ); }
     97 
     98     /**
     99      * Insert item x into the priority queue; allows duplicates.
    100      */
    101     void insert( Comparable && x )
    102       { BinomialQueue oneItem{ std::move( x ) }; merge( oneItem ); }
    103     
    104     /**
    105      * Remove the smallest item from the priority queue.
    106      * Throws UnderflowException if empty.
    107      */
    108     void deleteMin( )
    109     {
    110         Comparable x;
    111         deleteMin( x );
    112     }
    113 
    114     /**
    115      * Remove the minimum item and place it in minItem.
    116      * Throws UnderflowException if empty.
    117      */
    118     void deleteMin( Comparable & minItem )
    119     {
    120         if( isEmpty( ) )
    121             throw UnderflowException{ };
    122 
    123         int minIndex = findMinIndex( );
    124         minItem = theTrees[ minIndex ]->element;
    125 
    126         BinomialNode *oldRoot = theTrees[ minIndex ];
    127         BinomialNode *deletedTree = oldRoot->leftChild;
    128         delete oldRoot;
    129 
    130         // Construct H''
    131         BinomialQueue deletedQueue;
    132         deletedQueue.theTrees.resize( minIndex );
    133         deletedQueue.currentSize = ( 1 << minIndex ) - 1;
    134         for( int j = minIndex - 1; j >= 0; --j )
    135         {
    136             deletedQueue.theTrees[ j ] = deletedTree;
    137             deletedTree = deletedTree->nextSibling;
    138             deletedQueue.theTrees[ j ]->nextSibling = nullptr;
    139         }
    140 
    141         // Construct H'
    142         theTrees[ minIndex ] = nullptr;
    143         currentSize -= deletedQueue.currentSize + 1;
    144 
    145         merge( deletedQueue );
    146     }
    147 
    148     /**
    149      * Make the priority queue logically empty.
    150      */
    151     void makeEmpty( )
    152     {
    153         currentSize = 0;
    154         for( auto & root : theTrees )
    155             makeEmpty( root );
    156     }
    157 
    158     /**
    159      * Merge rhs into the priority queue.
    160      * rhs becomes empty. rhs must be different from this.
    161      * Exercise 6.35 needed to make this operation more efficient.
    162      */
    163     void merge( BinomialQueue & rhs )
    164     {
    165         if( this == &rhs )    // Avoid aliasing problems
    166             return;
    167 
    168         currentSize += rhs.currentSize;
    169 
    170         if( currentSize > capacity( ) )
    171         {
    172             int oldNumTrees = theTrees.size( );
    173             int newNumTrees = max( theTrees.size( ), rhs.theTrees.size( ) ) + 1;
    174             theTrees.resize( newNumTrees );
    175             for( int i = oldNumTrees; i < newNumTrees; ++i )
    176                 theTrees[ i ] = nullptr;
    177         }
    178 
    179         BinomialNode *carry = nullptr;
    180         for( int i = 0, j = 1; j <= currentSize; ++i, j *= 2 )
    181         {
    182             BinomialNode *t1 = theTrees[ i ];
    183             BinomialNode *t2 = i < rhs.theTrees.size( ) ? rhs.theTrees[ i ] : nullptr;
    184 
    185             int whichCase = t1 == nullptr ? 0 : 1;
    186             whichCase += t2 == nullptr ? 0 : 2;
    187             whichCase += carry == nullptr ? 0 : 4;
    188 
    189             switch( whichCase )
    190             {
    191               case 0: /* No trees */
    192               case 1: /* Only this */
    193                 break;
    194               case 2: /* Only rhs */
    195                 theTrees[ i ] = t2;
    196                 rhs.theTrees[ i ] = nullptr;
    197                 break;
    198               case 4: /* Only carry */
    199                 theTrees[ i ] = carry;
    200                 carry = nullptr;
    201                 break;
    202               case 3: /* this and rhs */
    203                 carry = combineTrees( t1, t2 );
    204                 theTrees[ i ] = rhs.theTrees[ i ] = nullptr;
    205                 break;
    206               case 5: /* this and carry */
    207                 carry = combineTrees( t1, carry );
    208                 theTrees[ i ] = nullptr;
    209                 break;
    210               case 6: /* rhs and carry */
    211                 carry = combineTrees( t2, carry );
    212                 rhs.theTrees[ i ] = nullptr;
    213                 break;
    214               case 7: /* All three */
    215                 theTrees[ i ] = carry;
    216                 carry = combineTrees( t1, t2 );
    217                 rhs.theTrees[ i ] = nullptr;
    218                 break;
    219             }
    220         }
    221 
    222         for( auto & root : rhs.theTrees )
    223             root = nullptr;
    224         rhs.currentSize = 0;
    225     }    
    226 
    227 
    228   private:
    229     struct BinomialNode
    230     {
    231         Comparable    element;
    232         BinomialNode *leftChild;
    233         BinomialNode *nextSibling;
    234 
    235         BinomialNode( const Comparable & e, BinomialNode *lt, BinomialNode *rt )
    236           : element{ e }, leftChild{ lt }, nextSibling{ rt } { }
    237         
    238         BinomialNode( Comparable && e, BinomialNode *lt, BinomialNode *rt )
    239           : element{ std::move( e ) }, leftChild{ lt }, nextSibling{ rt } { }
    240     };
    241 
    242     const static int DEFAULT_TREES = 1;
    243 
    244     vector<BinomialNode *> theTrees;  // An array of tree roots
    245     int currentSize;                  // Number of items in the priority queue
    246     
    247     /**
    248      * Find index of tree containing the smallest item in the priority queue.
    249      * The priority queue must not be empty.
    250      * Return the index of tree containing the smallest item.
    251      */
    252     int findMinIndex( ) const
    253     {
    254         int i;
    255         int minIndex;
    256 
    257         for( i = 0; theTrees[ i ] == nullptr; ++i )
    258             ;
    259 
    260         for( minIndex = i; i < theTrees.size( ); ++i )
    261             if( theTrees[ i ] != nullptr &&
    262                 theTrees[ i ]->element < theTrees[ minIndex ]->element )
    263                 minIndex = i;
    264 
    265         return minIndex;
    266     }
    267 
    268     /**
    269      * Return the capacity.
    270      */
    271     int capacity( ) const
    272       { return ( 1 << theTrees.size( ) ) - 1; }
    273 
    274     /**
    275      * Return the result of merging equal-sized t1 and t2.
    276      */
    277     BinomialNode * combineTrees( BinomialNode *t1, BinomialNode *t2 )
    278     {
    279         if( t2->element < t1->element )
    280             return combineTrees( t2, t1 );
    281         t2->nextSibling = t1->leftChild;
    282         t1->leftChild = t2;
    283         return t1;
    284     }
    285 
    286     /**
    287      * Make a binomial tree logically empty, and free memory.
    288      */
    289     void makeEmpty( BinomialNode * & t )
    290     {
    291         if( t != nullptr )
    292         {
    293             makeEmpty( t->leftChild );
    294             makeEmpty( t->nextSibling );
    295             delete t;
    296             t = nullptr;
    297         }
    298     }
    299 
    300     /**
    301      * Internal method to clone subtree.
    302      */
    303     BinomialNode * clone( BinomialNode * t ) const
    304     {
    305         if( t == nullptr )
    306             return nullptr;
    307         else
    308             return new BinomialNode{ t->element, clone( t->leftChild ), clone( t->nextSibling ) };
    309     }
    310 };
    311 
    312 #endif

    测试:

     1 #include "BinomialQueue.h"
     2 #include <iostream>
     3 using namespace std;
     4 
     5 int main( )
     6 {
     7     int numItems = 100000;
     8     BinomialQueue<int> h;
     9     BinomialQueue<int> h1;
    10     BinomialQueue<int> h2;
    11     int i = 37;
    12 
    13     cout << "Begin test..." << endl;
    14     for( i = 37; i != 0; i = ( i + 37 ) % numItems )
    15         if( i % 2 == 0 )
    16             h1.insert( i );
    17         else
    18             h.insert( i );
    19 
    20     h.merge( h1 );
    21     h2 = h;
    22 
    23     for( i = 1; i < numItems; ++i )
    24     {
    25 
    26         int x;
    27         h2.deleteMin( x );
    28         if( x != i )
    29             cout << "Oops! " << i << endl;
    30     }
    31 
    32     if( !h1.isEmpty( ) )
    33         cout << "Oops! h1 should have been empty!" << endl;
    34 
    35     cout << "End of test... no output is good" << endl;
    36 
    37     return 0;
    38 }
  • 相关阅读:
    JAVA EE企业级开发四步走
    区间dp笔记√
    TYVJ P1016 装箱问题
    树状数组的笔记√(hzwer blog)
    忠诚//线段树
    线段树笔记√
    P1005 采药
    超级书架【未完】
    P1082 找朋友
    数字三角形系列
  • 原文地址:https://www.cnblogs.com/dracohan/p/3891193.html
Copyright © 2020-2023  润新知