[DS] 易於合併的堆:左式堆和斜堆C++實現

原始的二叉堆使用數組實現,是一個徹底二叉樹,其實現簡單,可是在合併方面不盡人意,只能經過構建一個新的堆來實現兩個堆的合併,時間複雜度爲O(N)。
而左式堆和斜堆是兩種合併高效的堆,而且左式堆以及斜堆的insert以及deleteMin等操做都是以merge操做爲基礎的。merge時間複雜度能夠達到O(logN)。node

左式堆(Leftist Heaps)使用指針實現,它仍然使用二叉樹的結構實現,仍知足堆序性,但它不是徹底二叉樹。相比於二叉樹,其節點上增長了一個NPL (null path length)屬性,它指的是從該結點到達一個沒有兩個孩子的結點的最短距離,NULL的NPL爲-1。而左式堆的核心約束條件就是:任意結點的左孩子的Npl大於等於右孩子的Npl。ios

//
// Created by chnmagnus on 16-3-30.
//

#ifndef ADSPRO3_LEFTISTHEAP_H
#define ADSPRO3_LEFTISTHEAP_H

#include <iostream>
//the declaration of node class
template <class T>
class LNode{
public:
    int npl; //npl
    T data; //element
    LNode * left; //pointer to left child
    LNode * right; //point to right child
    LNode() = default; //default constructor
    //constructor
    LNode(T element):data(element),left(nullptr),right(nullptr),npl(0){}
};
//the declaration of leftist heap class
template <class T>
class LeftistHeap{
public:
    LNode<T> * root; //the root

    LeftistHeap():root(nullptr){} //constructor
    //merge two heap
    //and the result is current heap
    //instead another heap that is merged
    void merge(LeftistHeap another);
    LNode<T> * imerge(LNode<T>* a,LNode<T>* b);
    LNode<T> * iimerge(LNode<T>* a,LNode<T>* b);
    void insert(T element);//insert element
    void deleteMin();//delete the root
    void preprint(LNode<T>* LNode);//preorder print the heap
    void inprint(LNode<T>* LNode);//inorder print the heap
};
//the drive function of imerge and iimerge
template <class T>
void LeftistHeap<T>::merge(LeftistHeap another){
    this->root = imerge(this->root,another.root);
}
template <class T>
LNode<T>* LeftistHeap<T>::imerge(LNode<T> *a ,LNode<T> *b){
    if(a==nullptr) return b;
    if(b==nullptr) return a;
    if(a->data<b->data) return iimerge(a,b);
    else return iimerge(b,a);
}
template <class T>
LNode<T>* LeftistHeap<T>::iimerge(LNode<T> *a ,LNode<T> *b){
    if(a->left==nullptr){
        a->left = b;
    }else{
        a->right = imerge(a->right,b);
        if(a->left->npl<a->right->npl){
            LNode<T>* tm = a->left;
            a->left = a->right;
            a->right = tm;
        }
        a->npl = a->right->npl+1;
    }
    return a;
}
template <class T>
void LeftistHeap<T>::insert(T element){
    LNode<T>* newLNode = new LNode<T>(element);
    root = imerge(root,newLNode);
}
template <class T>
void LeftistHeap<T>::deleteMin(){
    if(root==nullptr) return ;
    LNode<T>* tem = root;
    root = imerge(root->left,root->right);
    delete tem;
    tem = nullptr;
}
template<class T>
void LeftistHeap<T>::preprint(LNode<T>* LNode){
    if(LNode==nullptr) return ;
    std::cout<<LNode->data<<" ";
    if(nullptr!=LNode->left) preprint(LNode->left);
    if(nullptr!=LNode->right) preprint(LNode->right);
}
template<class T>
void LeftistHeap<T>::inprint(LNode<T>* LNode){
    if(LNode==nullptr) return ;
    if(nullptr!=LNode->left) inprint(LNode->left);
    std::cout<<LNode->data<<" ";
    if(nullptr!=LNode->right) inprint(LNode->right);
}
#endif //ADSPRO3_LEFTISTHEAP_H

斜堆(Skew Heap)與左式堆很是類似,惟一的不一樣是,其節點上並無NPL屬性。左式堆的merge操做老是在右子樹上進行,當某節點出現左子樹NPL小於右子樹時,則交換左右子樹。而斜堆不判斷NPL屬性,每一次合併都會無條件交換左右子樹,經過這種方式來使其攤還時間複雜度達到O(logN)。代碼以下。數組

//
// Created by chnmagnus on 16-3-30.
//

#ifndef ADSPRO3_SKEWHEAP_H
#define ADSPRO3_SKEWHEAP_H
#include <iostream>
//the declaration of node class
template <class T>
class SNode{
public:
    T data; //the data
    SNode * left; //pointer to left child
    SNode * right; //pointer to right child
    SNode() = default; //default constructor
    //constructor
    SNode(T element):data(element),left(nullptr),right(nullptr){}
};
//the declaration of skew heap class
template <class T>
class SkewHeap{
public:
    SNode<T> * root; // the root
    SkewHeap():root(nullptr){} //constructor
    //merge function
    void merge(SkewHeap another);
    SNode<T> * imerge(SNode<T>* a,SNode<T>* b);
    SNode<T> * iimerge(SNode<T>* a,SNode<T>* b);
    void insert(T element);//insert element
    void deleteMin();//delete the min element
    void preprint(SNode<T>* SNode); //print heap in preorder
    void inprint(SNode<T>* SNode); //print heap in inorder
};
//the drive function of imerge and iimerge
template <class T>
void SkewHeap<T>::merge(SkewHeap another){
    this->root = imerge(this->root,another.root);
}
template <class T>
SNode<T>* SkewHeap<T>::imerge(SNode<T> *a ,SNode<T> *b){
    if(a==nullptr) return b;
    if(b==nullptr) return a;
    if(a->data<b->data) return iimerge(a,b);
    else return iimerge(b,a);
}
template <class T>
SNode<T>* SkewHeap<T>::iimerge(SNode<T> *a ,SNode<T> *b){
    if(a->right==nullptr){
        a->right = b;
    }else{
        a->right = imerge(a->right,b);
    }
    SNode<T>* tm = a->left;
    a->left = a->right;
    a->right = tm;
    return a;
}
template <class T>
void SkewHeap<T>::insert(T element){
    SNode<T>* newSNode = new SNode<T>(element);
    root = imerge(root,newSNode);
}
template <class T>
void SkewHeap<T>::deleteMin(){
    if(root==nullptr) return ;
    SNode<T>* tem = root;
    root = imerge(root->left,root->right);
    delete tem;
    tem = nullptr;
}
template<class T>
void SkewHeap<T>::preprint(SNode<T>* SNode){
    if(SNode==nullptr) return ;
    std::cout<<SNode->data<<" ";
    if(nullptr!=SNode->left) preprint(SNode->left);
    if(nullptr!=SNode->right) preprint(SNode->right);
}
template<class T>
void SkewHeap<T>::inprint(SNode<T>* SNode){
    if(SNode==nullptr) return ;
    if(nullptr!=SNode->left) inprint(SNode->left);
    std::cout<<SNode->data<<" ";
    if(nullptr!=SNode->right) inprint(SNode->right);
}
#endif //ADSPRO3_SKEWHEAP_H

另附普通堆的實現:this

//
// Created by chnmagnus on 16-3-31.
//

#ifndef ADSPRO3_ORIGINHEAP_H
#define ADSPRO3_ORIGINHEAP_H
#include <iostream>
//the declaration of heap class
template <class T>
class OriginHeap{
public:
    int capacity;//the total capacity
    int size; //current element num
    T* Elements; //elements

    //the function declaration and the comment
    OriginHeap(); //constructor
    OriginHeap(int capacity); //constructor
    ~OriginHeap(); //destructor
    void percolateup(int i); //percolate up
    void percolatedown(int i); //percolate down
    T finfMin(); //return the root data
    bool isEmpty(); //is empty?
    bool isFull(); //is full?
    void insert(T element); //insert element
    void deleteMin(); //delete the root data
    void merge(OriginHeap & another); //merge two heap
};

template <class T>
void OriginHeap<T>::percolateup(int i){
    T element = Elements[i];
    for(;Elements[i/2]>element&&i>=1;i/=2){
        Elements[i] = Elements[i/2];
    }
    Elements[i] = element;
}
template <class T>
void OriginHeap<T>::percolatedown(int i){
    T x = Elements[i];
    int child;
    for(;i*2<=size;i = child){
        child = i*2;
        if(child!=size&&Elements[child+1]<Elements[child])
            child++;
        if(x>Elements[child]){
            Elements[i] = Elements[child];
        }else{
            break;
        }
    }
    Elements[i] = x;
}
template <class T>
OriginHeap<T>::OriginHeap(){ //Constructor
    capacity = 100;
    size = 0;
    Elements = new T[capacity+1];
}
template <class T>
OriginHeap<T>::OriginHeap(int capacity){
    this->capacity = capacity;
    size = 0;
    Elements = new T[capacity+1];
}
template <class T>
OriginHeap<T>::~OriginHeap(){ //Destructor
    if(Elements){
        delete []Elements;
    }
    Elements = nullptr;
}
template <class T>
void OriginHeap<T>::insert(T element){
    if(isFull()){
        std::cout<<"Heap is full"<<std::endl;
        return ;
    }
    Elements[++size] = element;
    percolateup(size);
}
template <class T>
void OriginHeap<T>::deleteMin(){
    if(isEmpty()){
        std::cout<<"heap is empty"<<std::endl;
        return ;
    }
    Elements[1] = Elements[size--];
    percolatedown(1);

}
template <class T>
T OriginHeap<T>::finfMin(){
    return Elements[1];
}
template <class T>
void OriginHeap<T>::merge(OriginHeap & another){
    if(this->capacity<another.size+this->size){
        std::cout<<"cannot merge"<<std::endl;
        return ;
    }
    for(int i=1;i<=another.size;++i){
        Elements[++this->size] = another.Elements[i];
    }
    for(int i=size/2;i>=1;--i){
        percolatedown(i);
    }
}
template <class T>
bool OriginHeap<T>::isEmpty(){
    return size==0;
}
template <class T>
bool OriginHeap<T>::isFull(){
    return size==capacity;
}

#endif //ADSPRO3_ORIGINHEAP_H
相關文章
相關標籤/搜索