Guest User

Untitled

a guest
Apr 28th, 2017
198
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.66 KB | None | 0 0
  1. #ifndef BINOMIAL_QUEUE_H
  2. #define BINOMIAL_QUEUE_H
  3. #include <unordered_map>
  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. static int numOfElement = 0;
  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, 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.       {
  97.         BinomialQueue oneItem{ x };
  98.         pair<Comparable,BinomialNode*> anItem (x, oneItem.theTrees.at(0));
  99.         hashTable.insert(anItem);
  100.         numOfElement++;
  101.         merge( oneItem );
  102.       }
  103.  
  104.     /**
  105.      * Insert item x into the priority queue; allows duplicates.
  106.      */
  107.     void insert( Comparable && x )
  108.       {
  109.         BinomialQueue oneItem{ std::move( x ) };
  110.         pair<Comparable,BinomialNode*> anItem (x, oneItem.theTrees.at(0));
  111.         hashTable.insert(anItem);
  112.         numOfElement++;
  113.         merge( oneItem );
  114.       }
  115.    
  116.     /**
  117.      * Remove the smallest item from the priority queue.
  118.      * Throws UnderflowException if empty.
  119.      */
  120.     void deleteMin( )
  121.     {
  122.         Comparable x;
  123.         deleteMin( x );
  124.     }
  125.  
  126.     /**
  127.      * Remove the minimum item and place it in minItem.
  128.      * Throws UnderflowException if empty.
  129.      */
  130.     void deleteMin( Comparable & minItem )
  131.     {
  132.         if( isEmpty( ) )
  133.             throw UnderflowException{ };
  134.  
  135.         int minIndex = findMinIndex( );
  136.         minItem = theTrees[ minIndex ]->element;
  137.  
  138.         BinomialNode *oldRoot = theTrees[ minIndex ];
  139.         BinomialNode *deletedTree = oldRoot->leftChild;
  140.         deletedTree->parent = oldRoot;
  141.         delete oldRoot;
  142.  
  143.         // Construct H''
  144.         BinomialQueue deletedQueue;
  145.         deletedQueue.theTrees.resize( minIndex );
  146.         deletedQueue.currentSize = ( 1 << minIndex ) - 1;
  147.         for( int j = minIndex - 1; j >= 0; --j )
  148.         {
  149.             deletedQueue.theTrees[ j ] = deletedTree;
  150.             deletedTree = deletedTree->nextSibling;
  151.             deletedQueue.theTrees[ j ]->nextSibling = nullptr;
  152.         }
  153.  
  154.         // Construct H'
  155.         theTrees[ minIndex ] = nullptr;
  156.         currentSize -= deletedQueue.currentSize + 1;
  157.  
  158.         merge( deletedQueue );
  159.     }
  160.  
  161.     /**
  162.      * Make the priority queue logically empty.
  163.      */
  164.     void makeEmpty( )
  165.     {
  166.         currentSize = 0;
  167.         for( auto & root : theTrees )
  168.             makeEmpty( root );
  169.     }
  170.  
  171.     /**
  172.      * Merge rhs into the priority queue.
  173.      * rhs becomes empty. rhs must be different from this.
  174.      * Exercise 6.35 needed to make this operation more efficient.
  175.      */
  176.     void merge( BinomialQueue & rhs )
  177.     {
  178.         if( this == &rhs )    // Avoid aliasing problems
  179.             return;
  180.  
  181.         currentSize += rhs.currentSize;
  182.  
  183.         if( currentSize > capacity( ) )
  184.         {
  185.             int oldNumTrees = theTrees.size( );
  186.             int newNumTrees = max( theTrees.size( ), rhs.theTrees.size( ) ) + 1;
  187.             theTrees.resize( newNumTrees );
  188.             for( int i = oldNumTrees; i < newNumTrees; ++i )
  189.                 theTrees[ i ] = nullptr;
  190.         }
  191.  
  192.         BinomialNode *carry = nullptr;
  193.         for( int i = 0, j = 1; j <= currentSize; ++i, j *= 2 )
  194.         {
  195.             BinomialNode *t1 = theTrees[ i ];
  196.             BinomialNode *t2 = i < rhs.theTrees.size( ) ? rhs.theTrees[ i ] : nullptr;
  197.  
  198.             int whichCase = t1 == nullptr ? 0 : 1;
  199.             whichCase += t2 == nullptr ? 0 : 2;
  200.             whichCase += carry == nullptr ? 0 : 4;
  201.  
  202.             switch( whichCase )
  203.             {
  204.               case 0: /* No trees */
  205.               case 1: /* Only this */
  206.                 break;
  207.               case 2: /* Only rhs */
  208.                 theTrees[ i ] = t2;
  209.                 rhs.theTrees[ i ] = nullptr;
  210.                 break;
  211.               case 4: /* Only carry */
  212.                 theTrees[ i ] = carry;
  213.                 carry = nullptr;
  214.                 break;
  215.               case 3: /* this and rhs */
  216.                 carry = combineTrees( t1, t2 );
  217.                 theTrees[ i ] = rhs.theTrees[ i ] = nullptr;
  218.                 break;
  219.               case 5: /* this and carry */
  220.                 carry = combineTrees( t1, carry );
  221.                 theTrees[ i ] = nullptr;
  222.                 break;
  223.               case 6: /* rhs and carry */
  224.                 carry = combineTrees( t2, carry );
  225.                 rhs.theTrees[ i ] = nullptr;
  226.                 break;
  227.               case 7: /* All three */
  228.                 theTrees[ i ] = carry;
  229.                 carry = combineTrees( t1, t2 );
  230.                 rhs.theTrees[ i ] = nullptr;
  231.                 break;
  232.             }
  233.         }
  234.  
  235.         for( auto & root : rhs.theTrees )
  236.             root = nullptr;
  237.         rhs.currentSize = 0;
  238.     }  
  239.     /*
  240.  
  241.     */
  242.  
  243.     // Checks if the number is in the hash table
  244.     bool contains(const Comparable &number){
  245.  
  246.       auto it = hashTable.find(number);
  247.       if(it == hashTable.end()){
  248.         return false;
  249.       }
  250.       else{
  251.         return true;
  252.       }
  253.     }
  254.  
  255.     // Deletes an item from hash table
  256.     bool deleteItem( const Comparable  &number ){
  257.      
  258.       // Finds the minimum
  259.       Comparable minimum = findMin();
  260.       Comparable temp = 0;
  261.       if(contains(number) == true){
  262.         BinomialNode *curr = hashTable.at(number);
  263.         // Swap parent with the child to percolate up
  264.         while(curr->parent != nullptr){
  265.           // Swap parent with the child to percolate up
  266.           temp = curr->element;
  267.           curr->element = curr->parent->element;
  268.           curr->parent->element = temp;
  269.           // Swap pointers
  270.           std::swap(curr, curr->parent);
  271.         }
  272.         // Set current as a small number and delete
  273.         curr->element = minimum-1;
  274.         deleteMin();
  275.         hashTable.erase(hashTable.find(number));
  276.         return true;
  277.       }
  278.       return false;
  279.     }
  280.  
  281.   private:
  282.  
  283.     struct BinomialNode
  284.     {
  285.         Comparable    element;
  286.         BinomialNode *leftChild;
  287.         BinomialNode *nextSibling;
  288.         BinomialNode *parent;
  289.  
  290.         BinomialNode( const Comparable & e, BinomialNode *lt, BinomialNode *rt, BinomialNode *p )
  291.           : element{ e }, leftChild{ lt }, nextSibling{ rt }, parent { p } { }
  292.        
  293.         BinomialNode( Comparable && e, BinomialNode *lt, BinomialNode *rt, BinomialNode *p )
  294.           : element{ std::move( e ) }, leftChild{ lt }, nextSibling{ rt }, parent{ p } { }
  295.     };
  296.  
  297.     const static int DEFAULT_TREES = 1;
  298.  
  299.     vector<BinomialNode *> theTrees;  // An array of tree roots
  300.     int currentSize;                  // Number of items in the priority queue
  301.  
  302.     // Hash table
  303.     unordered_map<Comparable , BinomialNode*>hashTable;
  304.    
  305.     /**
  306.      * Find index of tree containing the smallest item in the priority queue.
  307.      * The priority queue must not be empty.
  308.      * Return the index of tree containing the smallest item.
  309.      */
  310.     int findMinIndex( ) const
  311.     {
  312.         int i;
  313.         int minIndex;
  314.  
  315.         for( i = 0; theTrees[ i ] == nullptr; ++i )
  316.             ;
  317.  
  318.         for( minIndex = i; i < theTrees.size( ); ++i )
  319.             if( theTrees[ i ] != nullptr &&
  320.                 theTrees[ i ]->element < theTrees[ minIndex ]->element )
  321.                 minIndex = i;
  322.  
  323.         return minIndex;
  324.     }
  325.  
  326.     /**
  327.      * Return the capacity.
  328.      */
  329.     int capacity( ) const
  330.       { return ( 1 << theTrees.size( ) ) - 1; }
  331.  
  332.     /**
  333.      * Return the result of merging equal-sized t1 and t2.
  334.      */
  335.     BinomialNode * combineTrees( BinomialNode *t1, BinomialNode *t2 )
  336.     {
  337.         if( t2->element < t1->element ){
  338.             // Set t1's parent as t2 because t2->element is smaller
  339.             t1->parent = t2;
  340.             return combineTrees( t2, t1);
  341.         }
  342.         t2->nextSibling = t1->leftChild;
  343.         t1->leftChild = t2;
  344.         // t1 is the parent of t2
  345.         t2->parent = t1;
  346.  
  347.         return t1;
  348.     }
  349.  
  350.     /**
  351.      * Make a binomial tree logically empty, and free memory.
  352.      */
  353.     void makeEmpty( BinomialNode * & t )
  354.     {
  355.         if( t != nullptr )
  356.         {
  357.             makeEmpty( t->leftChild );
  358.             makeEmpty( t->nextSibling );
  359.             delete t;
  360.             t = nullptr;
  361.         }
  362.     }
  363.  
  364.     /**
  365.      * Internal method to clone subtree.
  366.      */
  367.     BinomialNode * clone( BinomialNode * t ) const
  368.     {
  369.         if( t == nullptr )
  370.             return nullptr;
  371.         else
  372.             return new BinomialNode{ t->element, clone( t->leftChild ), clone( t->nextSibling ), clone (t->parent) };
  373.     }
  374. };
  375.  
  376. #endif
Advertisement
Add Comment
Please, Sign In to add comment