二项堆

二叉堆

图片说明

template<typename T,size_t _n>
struct hep{
    int n;T *q;
    hep(){n=0;q=new int[_n];}
    ~hep(){delete []q;}
    void up(int i){ //上浮
        for(;i>1;i>>=1)
        if(q[i]<q[i>>1])swap(q[i],q[i>>1]);
    }
    void down(int i){ //下浮
        while((i<<1)<=n){
            int k=i<<1;
            if(k<n&&q[k+1]<q[k])++k;
            if(q[i]>q[k])swap(q[i],q[k]),i=k;
            else return;
        }
    }
    void push(const T& x){
        q[++n]=x;up(n);
    }
    void pop(){
        swap(q[1],q[n--]);
        down(1);
    }
    T top(){return q[1];}
    bool empty(){return n==0;}
};

二项堆

定义:

  • 度数为0的二项树只包含一个结点
  • 度数为的二项树有一个根结点,根结点下有个子女,每个子女分别是度数分别为的二项树的根
    图片说明
  • 度数为的二项树共有个节点,深度为处有个节点。
  • 每棵二项树都满足最小堆性质,即结点关键字大于等于其父结点的值
  • 不能有两棵或以上的二项树有相同度数(包括度数为0)。换句话说,具有度数k的二项树有0个或1个。
    比如的二进制为,所以由度数为的三棵树组成。
    一个含13个节点的二项堆
  • 二项堆插入操作,平摊分析复杂度为,个节点的堆,最多有棵树,查找,删除时间为
    二项堆的内存结构图:
    图片说明
template<typename T>
struct BinomiaNode{
    BinomiaNode():degree(0){
        val=0;
        parent=NULL;child=NULL;next=NULL;
    }
    T val;
    BinomiaNode *parent;
    BinomiaNode *child;
    BinomiaNode *next;
    size_t degree;
};

template<typename T,typename node=BinomiaNode<T>>
class BinomiaHeap{
public:
    BinomiaNode(){root=NULL;}
    bool empty()const{return root==NULL;}
    T top(){
        assert(empty());
        node *p=root;T key=root->val;
        while(p){
            if(p->val<key)key=p->val;
            p=p->next;
        }
        return key;
    }
    void pop(){
        erase(top());
    }
    void union_heap(BinomiaHeap<T> rhs){
        if(rhs&&rhs.root)root=union_heap(root,rhs.root);
    }
    void insert(const T& key){
        if(find(key))return;
        node* rt=new node();
        rt->val=key;
        root=union_heap(root,rt);
    }
    bool find(const T& key){return search(root,key)!=NULL;}
    void erase(const T& key){
        root=erase(root,key);
    }
private:
    node* erase(node* rt,const T& key){
        if(rt==NULL)return rt;
        node *p=search(rt,key);
        if(p==NULL)return rt;
        node* parent=p->parent;
        while(parent){
            p->val^=parent->val^=p->val;
            p=parent;parent=parent->parent;
        }
        node *prev=NULL;
        node *pos=rt;
        while(pos!=p)prev=pos,pos=pos->next;
        if(prev)prev->next=p->next;
        else rt=p->next;
        rt=union_heap(rt,reverse(p->child));
        p=NULL;return rt;
    }
    node* search(node* rt,const T& key){
        node *child,*parent=rt;
        while(parent){
            if(parent->val==key)return parent;
            else {
                child=search(parent->child,key);
                if(child)return child;
                parent=parent->next;
            }
        }
        return NULL;
    }
    node* reverse(node* rt){
        if(rt==NULL)return rt;
        node *_next,*tail=NULL;
        rt->parent=NULL;
        while(rt->next){
            _next=rt->next;
            rt->next=tail;
            tail=rt;rt=_next;
            rt->parent=NULL;
        }rt->next=tail;
        return rt;
    }

    void link(node* &child,node* &rt){
        child->parent=rt;
        child->next=rt->child;
        rt->child=child;rt->degree++;
    }
    node* merge(node* h1,node* h2){
        if(!h1)return h2;
        if(!h2)return h1;
        node* rt=NULL,*_next=NULL,*h=NULL;
        while(h1&&h2){
            if(h1->degree<=h2->degree)
            h=h1,h1=h1->next;
            else h=h2,h2=h2->next;

            if(_next==NULL){
                _next=h;rt=h;
            }else{
                _next->next=h;
                _next=h;
            }
            if(!h1&&h2)_next->next=h2;
            if(h1&&!h2)_next->next=h1;
        }
        return rt;
    }
    node* reverse_list(node* rt){
        if(rt==NULL)return rt;
        node* p=NULL;
        while(rt){
            node* q=rt;
            rt=rt->next;
            q->next=p;
            p=q;
        }
        return p;
    }
    node* union_heap(node* h1,node* h2){
        node* rt=merge(h1,h2);
        if(rt==NULL||rt->next==NULL)return rt;
        rt=reverse_list(rt);
        stack<node*>S;
        for(node *p=rt;p;p=p->next){
            while(!S.empty()&&S.top()->degree==p->degree){
                node* q=S.top();
                link(q,p);
                S.pop();
            }
            S.push(p);
        }
        node* p=NULL;
        while(!S.empty()){
            node* q=S.top();
            S.pop();
            q->next=p;
            p=q;
        }
        return reverse_list(p);
    }
    node *root;
};

合并操作:
图片说明

删除操作:
图片说明

Hello Code 文章被收录于专栏

放些代码相关

全部评论

相关推荐

ArisRobert:统一解释一下,第4点的意思是,公司按需通知员工,没被通知到的员工是没法去上班的,所以只要没被通知到,就自动离职。就是一种比较抽象的裁员。
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务