原始的二叉堆使用數組實現,是一個徹底二叉樹,其實現簡單,可是在合併方面不盡人意,只能經過構建一個新的堆來實現兩個堆的合併,時間複雜度爲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