堆——二项队列

来源:互联网 发布:网络安全管理心得 编辑:程序博客网 时间:2024/05/21 21:42

二项队列由一系列二项树组成,每个高度只允许一棵二项树。每棵树Bk由一个根和Bk-1…B0组成。删除最小值操作是先找到最小根值的树,然后删掉树根,得到新的一组二项队列Bk-1…B0。将两个队列合并,便完成了删除最小值操作。

#include <vector>template <typename Comparable>class BinomialQueue{public:    BinomialQueue();    BinomialQueue(const Comparable & item);    BinomialQueue(const BinomialQueue & rhs);    BinomialQueue(BinomialQueue && rhs);    ~BinomialQueue();    BinomialQueue & operator=(const BinomialQueue & rhs);    BinomialQueue & operator=(BinomialQueue && rhs);    bool isEmpty()const;    const Comparable & findMin()const;    void insert(const Comparable & x);    void insert(Comparable && x);    void deleteMin();    void deleteMin(Comparable & minItem);    void makeEmpty();    void merge(BinomialQueue & rhs);private:    struct BinomialNode    {        Comparable   element;        BinomialNode *leftChild;        BinomialNode *nextSibling;        BinomialNode(const Comparable & e,BinomialNode * lt,BinomialNode *rt)        :element(e),leftChild(lt),nextSibling(rt){}        BinomialNode(Comparable && e,BinomialNode * lt,BinomialNode *rt)        :element(std::move(e)),leftChild(lt),nextSibling(rt){}    };    const static int DEFAULT_TREES=1;    std::vector<BinomialNode *> theTrees;    int currentSize;                        //优先队列中的项数    int findMinIndex()const;    int capacity()const                     //数组最多能存储的项数    {        int Num=0;        int s=1;        for(int i=0;i<theTrees.size();++i)        {            Num+=s;            s*=2;        }        return Num;    }    BinomialNode * combineTrees(BinomialNode *t1,BinomialNode *t2);    void makeEmpty(BinomialNode * & t);    BinomialNode * clone(BinomialNode * t)const;};//合并同样大小的二项树template <typename Comparable>typename BinomialQueue<Comparable>::BinomialNode *BinomialQueue<Comparable>::combineTrees(BinomialNode *t1, BinomialNode *t2){    if(t2->element<t1->element)        return combineTrees(t2, t1);    t2->nextSibling=t1->leftChild;    t1->leftChild=t2;    return t1;}template <typename Comparable>void BinomialQueue<Comparable>::merge(BinomialQueue & rhs){    if(this==&rhs)        return;    currentSize+=rhs.currentSize;    if(currentSize>capacity())  //capacity代表当前数组能容纳的最多项数    {        int oldNumTrees=theTrees.size();        int newNumTrees=max(theTrees.size(),rhs.theTrees.size())+1;        theTrees.resize(newNumTrees);        for(int i=oldNumTrees;i<newNumTrees;++i)            theTrees[i]=nullptr;    }    BinomialNode *carry=nullptr;    //由上一位合并而来的    for(int i=0,j=1;j<=currentSize;++i,j*=2)    {        BinomialNode *t1=theTrees[i];        BinomialNode *t2=i<rhs.theTrees.size()?rhs.theTrees[i]:nullptr;        int whichcase=t1==nullptr?0:1;        whichcase+=t2==nullptr?0:2;        whichcase+=carry==nullptr?0:4;  //类似加法,carry代表进位        switch (whichcase) {            case 0:                     //都是空            case 1:                     //只有this                break;            case 2:                     //只有rhs                theTrees[i]=t2;                rhs.theTrees[i]=nullptr;                break;            case 4:                     //只有carry                theTrees[i]=carry;                carry=nullptr;                break;            case 3:                     //this和rhs                carry=combineTrees(t1, t2);                theTrees[i]=rhs.theTrees[i]=nullptr;                break;            case 5:                     //this和carry                carry=combineTrees(t1, carry);                theTrees[i]=nullptr;                break;            case 6:                     //carry和rhs                carry=combineTrees(carry, t2);                rhs.theTrees[i]=nullptr;                break;            case 7:                     //三者都有                theTrees[i]=carry;                carry=combineTrees(carry, t2);                rhs.theTrees[i]=nullptr;                break;            default:                break;        }    }    for(auto & root:rhs.theTrees)        root=nullptr;    rhs.currentSize=0;}template <typename Comparable>int BinomialQueue<Comparable>::findMinIndex()const{    int minIndex;    int i;    for(int i=0;theTrees[i]==nullptr;++i)        ;    for(minIndex=i;i<theTrees.size();++i)        if(theTrees[i]!=nullptr&&theTrees[i]->element<theTrees[minIndex]->element)        {            minIndex=i;        }    return minIndex;}template <typename Comparable>void BinomialQueue<Comparable>::deleteMin(Comparable & minItem){    //if(isEmpty())        //throw UnderflowException{};    int minIndex=findMinIndex();    minItem=theTrees[minIndex]->element;    BinomialNode *oldRoot=theTrees[minIndex];    BinomialNode *deletedTree=oldRoot->leftChild;    delete oldRoot;    BinomialQueue deletedQueue;    deletedQueue.theTrees.resize(minIndex+1);   //应该有minIndex个二项树    //将1左移minIndex位得到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=nullptr;    }    theTrees[minIndex]=nullptr;    //因为将minIndex处删除掉了,所以currentSize要减去它的项数    currentSize-=deletedQueue.currentSize+1;    merge(deletedQueue);}
原创粉丝点击