Data Structures (Weiss) Chapter 6: Binomial Queue

//

//  main.cpp

//  Data Structure TRY1

//

//  Created by zr9558 on 6/7/13.

//  Copyright (c) 2013 zr9558. All rights reserved.

//



// Data Structure C++, Weiss, P.246 Binomial queue


#include<iostream>

using namespace std;

#include<vector>

#include<math.h>


template<typename Comparable>

class BinomialQueue

{

public:

    BinomialQueue();

    BinomialQueue( const Comparable & item);

    BinomialQueue( const BinomialQueue &rhs);

    ~BinomialQueue();

    

    bool isEmpty() const;

    const Comparable & findMin() const;

    

    void insert( const Comparable &x);

    void deleteMin();

    void deleteMin( Comparable & minItem);

    

    void makeEmpty();

    void merge( BinomialQueue &rhs);

    

    const BinomialQueue & operator=( const BinomialQueue &rhs);

    

    

private:

    struct BinomialNode

    {

        Comparable element;

        BinomialNode *leftChild;

        BinomialNode *nextSibling;

        

        BinomialNode( const Comparable & theElement, BinomialNode *lt=NULL, BinomialNode *rt=NULL)

        :element(theElement), leftChild(lt),nextSibling(rt){}

        

    };

    

    enum { DEFAULT_TREES=1};

    

    int currentSize; // Number of items in priority queue;

    vector<BinomialNode *> theTrees; // An array of tree roots;

    

    /* Find index of tree containing the smallest item in the priority queue.

       The priority queue must not be empty.

       Return the index of tree containing the smallest item.

     */

    int findMinIndex() const

    {

        int i;

        int minIndex;

        

        for( i=0; theTrees[i]==NULL; ++i) ;

        

        for( minIndex=i; i<theTrees.size(); ++i)

            if( theTrees[i]!=NULL && theTrees[i]->element<theTrees[minIndex]->element)

                minIndex=i;

    

        return minIndex;

    }

    

    int capacity() const

    {

        int sum=0;

        for( int i=0; i<theTrees.size(); ++i)

            sum+=pow(2,i);

        return sum;

    }

    

    // return the result of merging equal-sized t1 and t2;

    BinomialNode * combineTrees( BinomialNode *t1, BinomialNode *t2)

    {

        if( t2->element<t1->element)

            return combineTrees(t2,t1);

        

        t2->nextSibling=t1->leftChild;

        t1->leftChild=t2;

        return t1;

    }

    

    void makeEmpty( BinomialNode *&t)

    {

        if( t==NULL) return;

        

        makeEmpty(t->leftChild);

        makeEmpty(t->nextSibling);

        

        delete t;

    }

    

    BinomialNode * clone( BinomialNode *t) const

    {

        if( t==NULL) return NULL;

        

        return new BinomialNode(t->element, clone(t->leftChild), clone(t->nextSibling));

    }

    

};



template<typename Comparable>

const Comparable & BinomialQueue<Comparable>::findMin() const

{

    return theTrees[findMinIndex()]->element;

}


template<typename Comparable>

void BinomialQueue<Comparable>::insert(const Comparable &x)

{

    BinomialQueue temp(x);

    merge(temp);

}


template<typename Comparable>

void BinomialQueue<Comparable>::makeEmpty()

{

    for( int i=0; i!=theTrees.size(); ++i)

        makeEmpty(theTrees[i]);

}


template<typename Comparable>

bool BinomialQueue<Comparable>::isEmpty() const

{

    return currentSize==0;

}


template<typename Comparable>

BinomialQueue<Comparable>::BinomialQueue():currentSize(0)

{

    for( int i=0; i!=DEFAULT_TREES; ++i)

        theTrees.push_back(NULL);

}


template<typename Comparable>

BinomialQueue<Comparable>::BinomialQueue( const Comparable & item):currentSize(1)

{

    theTrees.push_back(new BinomialNode(item));

}


template<typename Comparable>

BinomialQueue<Comparable>::BinomialQueue( const BinomialQueue &rhs):currentSize(rhs.currentSize)

{

    for( int i=0; i!=rhs.theTrees.size(); ++i)

        theTrees.push_back(clone(rhs.theTrees[i]));

}


template<typename Comparable>

BinomialQueue<Comparable>::~BinomialQueue()

{

    makeEmpty();

}


template<typename Comparable>

const BinomialQueue<Comparable> & BinomialQueue<Comparable>::operator=(const BinomialQueue &rhs)

{

    if( this!=&rhs)

    {

        makeEmpty();

        theTrees.clear();

        currentSize=rhs.currentSize;

        for( int i=0; i!=rhs.theTrees.size(); ++i)

            theTrees.push_back(clone(rhs.theTrees[i]));

    }

    return *this;

}



/*

 Merge rhs into the priority queue.

 rhs becomes empty. rhs must be different from this.

 */

template<typename Comparable>

void BinomialQueue<Comparable>::merge(BinomialQueue & rhs)

{

    if( this==&rhs) return; // avoid aliasing problems

    

    currentSize+=rhs.currentSize;

    

    if( currentSize>capacity())

    {

        int oldNumTrees=int(theTrees.size());

        int newNumTrees=max(int(theTrees.size()), int(rhs.theTrees.size()))+1;

        theTrees.resize(newNumTrees);

        for( int i=oldNumTrees; i<newNumTrees; ++i)

            theTrees[i]=NULL;

    }

    

    BinomialNode *carry=NULL;

    for( int i=0, j=1; j<=currentSize; i++,j*=2)

    {

        BinomialNode *t1=theTrees[i];

        BinomialNode *t2=i<rhs.theTrees.size() ? rhs.theTrees[i]: NULL;

        

        int whichCase= t1==NULL ? 0 : 1;

        whichCase+= t2==NULL ? 0 : 2;

        whichCase+= carry==NULL ? 0 : 4;

        

        switch(whichCase)

        {

            case 0: // No trees;

            case 1: // only this

                break;

            case 2: // only rhs

                theTrees[i]=t2;

                rhs.theTrees[i]=NULL;

                break;

            case 3: // this and rhs

                carry=combineTrees(t1, t2);

                theTrees[i]=rhs.theTrees[i]=NULL;

                break;

            case 4: // only carry

                theTrees[i]=carry;

                carry=NULL;

                break;

            case 5: // this and carry;

                carry=combineTrees(t1, carry);

                theTrees[i]=NULL;

                break;

            case 6: // rhs and carry

                carry=combineTrees(t2, carry);

                rhs.theTrees[i]=NULL;

                break;

            case 7: // all three

                theTrees[i]=carry;

                carry=combineTrees(t1, t2);

                rhs.theTrees[i]=NULL;

                break;

        }

        

        

    }

    for( int i=0; i!=rhs.theTrees.size(); ++i)

        rhs.theTrees[i]=NULL;

    rhs.currentSize=0;

    

}



template<typename Comparable>

void BinomialQueue<Comparable>::deleteMin( Comparable & minItem)

{

    int minIndex=findMinIndex();

    minItem=theTrees[minIndex]->element;

    

    BinomialNode *oldRoot=theTrees[minIndex];

    BinomialNode *deletedTree=oldRoot->leftChild;

    

    delete oldRoot;

    

    // Construct H''

    BinomialQueue deletedQueue;

    deletedQueue.theTrees.resize(minIndex+1);

    deletedQueue.currentSize=(1<<minIndex)-1;

    for( int j=minIndex-1; j>=0; --j)

    {

        deletedQueue.theTrees[j]=deletedTree;

        deletedTree=deletedTree->nextSibling;

        deletedQueue.theTrees[j]->nextSibling=NULL;

    }

    

    // Construct H'

    theTrees[minIndex]=NULL;

    currentSize-=deletedQueue.currentSize+1;

    

    merge(deletedQueue);

}


template<typename Comparable>

void BinomialQueue<Comparable>::deleteMin()

{

    Comparable temp;

    deleteMin(temp);

}


int main()

{

    BinomialQueue<int> Q;

    for( int i=0; i<20; ++i)

        Q.insert(rand()%100);

    

    BinomialQueue<int> Q1, Q2(Q);

    Q1=Q;

    

    while( !Q.isEmpty())

    {

        cout<<Q.findMin()<<" ";

        Q.deleteMin();

    }

    cout<<endl;

    

    while( !Q1.isEmpty())

    {

        cout<<Q1.findMin()<<" ";

        Q1.deleteMin();

    }

    cout<<endl;

    

    while( !Q2.isEmpty())

    {

        cout<<Q2.findMin()<<" ";

        Q2.deleteMin();

    }

    cout<<endl;

    return 0;

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值