第十二章 优先队列

大根数(2叉 总) / 内含完全k叉树的大堆根

              

#include<iostream>
#include<queue>
#include<string>
using namespace std;
class Empty{
     private:
      string message;
    public:
      Empty(string str="The number of elements is 0") : message{str} {}
      string what(){return message;}
};
template<class T>
class maxHeap{//大根堆一定是一个完全二叉树  用数组表示
  
  public:
      maxHeap(int init=10);
      
     // ~maxHeap(){delete heap;}
        ~maxHeap(){}
      void push(const T& theElement);
      void pop();
      void initialize(T* theHeap,int theSize);//初始化一个非空大根堆 传进去一个没排序好的
      void show();
      
      ///---
      maxHeap(maxHeap<T> &x);//复制构造1
      void changeMax(T newElement);//替换最大1
      void remove(int i);//删除索引元素 1
      void newPop();//0
      

    private:
      T* heap;
      int heapSize;
      int arrayLength;
};
template<class T>
maxHeap<T>::maxHeap(int init){
         heap = new T[init+1];//从1开始
    arrayLength=init+1;
    heapSize=0;
}
template<class T>
void 
maxHeap<T>::pop(){
      if(heapSize==0)
       throw Empty();
    
    heap[1].~T();

    T lastElement= heap[heapSize--];

    int currentNode=1,child=2;//左子孩子是 2* 
     while(child<heapSize){
          if(child<heapSize&&heap[child]<heap[child+1])
             child++;//选择大的孩子移至父位 

             if(lastElement>=heap[child])
                   break;

                heap[currentNode]=heap[child];//元素上移
                currentNode=child;//搜索位置下移
                child*=2;

     }
         heap[currentNode]=lastElement;    
}
template<class T>
void 
maxHeap<T>::push(const T& theElement){
     if(heapSize==arrayLength-1){
            T* temp = new T[arrayLength*2];
        copy(heap+1,heap+arrayLength,temp+1);
       // delete [] heap;
        heap=temp;
        arrayLength*=2;
     }

    int currentNode= ++heapSize;
    while(currentNode!= 1 && heap[currentNode/2]<theElement){
             heap[currentNode]=heap[currentNode/2];//元素下移
             currentNode/=2;//搜索位置上移动
    }
             heap[currentNode]=theElement;
       
}
template<class T>
void 
maxHeap<T>::initialize(T* theHeap,int theSize){
       delete [] heap;
       heap= theHeap;
       heapSize=theSize;
       //复制基本的 

    for(int root= heapSize/2;root>=1;root--){//从最后一个有孩子的节点开始遍历
          T rootElement= heap[root];

          int child=root*2;

          while(child <= heapSize){//内while循环  把此root换到此子树的对应位置,使子树成为大堆跟
               if(child<heapSize&&heap[child]<heap[child+1])
                   child++;
                
                 if(rootElement>= heap[child])
                    break;

                   heap[child/2]= heap[child];
                   child*=2;
          }
            heap[child/2]=rootElement;
    }
}
template<class T>
void 
maxHeap<T>::show(){

    
 queue<int> q;
 
 q.push(1);
  int current=1;
      while(!q.empty()){
         current=q.front();
         q.pop();
         cout<<heap[current]<<" ";
    
        if(current*2<=heapSize)
          q.push(current*2);
        if(current*2+1<=heapSize)
          q.push(current*2+1);

      }
    cout<<endl;
}
template<class T>
maxHeap<T>:: maxHeap(maxHeap<T> &x){
       heapSize=x.heapSize;
       heap= new T[x.arrayLength];
       copy(x.heap,x.heap+heapSize+1,heap);
       arrayLength=x.arrayLength;
}
template<class T>
void 
maxHeap<T>:: changeMax(T newElement){
          if(heapSize==0)
            throw Empty();
      int currentNode=1;
      int child=2;
    while(currentNode<heapSize){
             if(child<heapSize&&heap[child]<heap[child+1])
                   child++;
                if(newElement>=heap[child])
                  break;
              heap[currentNode]=heap[child];
              currentNode=child;
              child*=2;        
    }
      heap[currentNode]=newElement;
}
template<class T>
void 
maxHeap<T>::remove(int i){
      T lastElement= heap[heapSize--];
        int currentNode=i;
       int child=i*2;

        while(currentNode<heapSize){
             if(child<heapSize&&heap[child]<heap[child+1])
                   child++;
                if(lastElement>=heap[child])
                  break;
              heap[currentNode]=heap[child];
              currentNode=child;
              child*=2;        
    }
            cout<<currentNode<<" "<<lastElement<<endl;
            heap[currentNode]=lastElement;
}
template<class T>
void
maxHeap<T>:: newPop(){
    
}
int main(){
    maxHeap<int> a;
    int heap[]={0,20,12,35,15,10,80,30,17,2,1};//从1 开始 统一
    a.initialize(heap,10);
    maxHeap<int> b(a);
    a.pop();
    a.pop();
    a.push(666);
    a.push(3);
    b.changeMax(11); 
 
    b.show();
    

}

12.1 

    基类在第五章总  

     基类是模板类,您需要通过this指针访问成员:

      为什么派生类不能访问受保护的基类成员? - VoidCC

template<class T>
class maxPriorityQueue{
  public:
    virtual ~maxPriorityQueue(){}
    virtual bool empty() const =0;
    virtual int size()const =0;
    virtual const T& top()=0;
    virtual void pop() =0;
    virtual void push(const T& theElement) =0;
};
template<class T>
class ArrayMaxPriorityQueue:public arrayList<T>,public maxPriorityQueue<T>{//无序线性表 
       
    public: //像我这样一个子类派生于 一个基类和一个纯虚函数 ,

//不行,纯虚函数必须在子类中全部实现
           
         bool empty() const {return this->empty();}
         int size()const {return this->size();}
        const T& top();
        void pop();
        void push(const T& theElement);

};
template<class T>
const T&
ArrayMaxPriorityQueue<T>::top(){
    
     T Max=0;
   for(int i=1;i<this->listSize;i++){
          if(this->element[i]>this->element[Max])
            Max=i;
   }
        
     return this->element[Max];
}
template<class T>
void
ArrayMaxPriorityQueue<T>::pop(){
     T temp = top();
     int i;
   for(i=0;i<this->listSize;i++){
          if(temp==this->element[i])
             break;
   }
      copy(this->element+i+1,this->element+this->listSize,this->element+i);
        this->listSize--;
}
template<class T>
void
ArrayMaxPriorityQueue<T>::push(const T& theElement){
      arrayList<T>:: push_back(theElement); //在派生类的普通成员函数中,使用基类作用域调用基类的静态成员函数和普通成员函数都可以
}
int main(){
    
    ArrayMaxPriorityQueue<int> b;
     b.push(55);
     b.push(100);
     cout<<b;
    //
 
    return 0;
 
}

12.2 

    思路一样的 ,具体实现换成 链表的操作 

12.3-4

     变为有序的 

           差别为:{

              有序的:pop和pop都为O(1) ,push为O(n) ,因为要查找插入的位置 

              无序的:push为O(1),pop,push为O(n),因为要查找对应值

}

12.5 

      就是哈希表+ 优先级队列 ,数组元素类型可以是链表头指针,也可以是一维数组 

        maxPriority就是桶的个数

12.6-9

    思路就是:

          删除:因为是完全二叉树,最后一个位置肯定没了,空的是第一个位置{

                    元素上移,搜索位置下移

}

          添加:多最后一个位置,空的是第一个位置 {

                    元素下移,搜索位置上移

}

    图就不画了 ,书上也有

12.10  

   用错位相减 

          

  用数学归纳法证明 - 百度文库 (baidu.com)

12.11 

   

template<class T>
maxHeap<T>:: maxHeap(maxHeap<T> &x){
       heapSize=x.heapSize;
       heap= new T[x.arrayLength];
       copy(x.heap,x.heap+heapSize+1,heap);
       arrayLength=x.arrayLength;
}

12.12 

    

template<class T>
void 
maxHeap<T>:: changeMax(T newElement){
          if(heapSize==0)
            throw Empty();
      int currentNode=1;
      int child=2;
    while(child<heapSize){
             if(child<heapSize&&heap[child]<heap[child+1])
                   child++;
                if(newElement>=heap[child])
                  break;
              heap[currentNode]=heap[child];
              currentNode=child;
              child*=2;        
    }
      heap[currentNode]=newElement;
}

12.13

    

template<class T>
void 
maxHeap<T>::remove(int i){
      T lastElement= heap[heapSize--];
        int currentNode=i;
       int child=i*2;

        while(currentNode<heapSize){
             if(child<heapSize&&heap[child]<heap[child+1])
                   child++;
                if(lastElement>=heap[child])
                  break;
              heap[currentNode]=heap[child];
              currentNode=child;
              child*=2;        
    }
            cout<<currentNode<<" "<<lastElement<<endl;
            heap[currentNode]=lastElement;
}

12.14 

    不会迭代器 ,代补 

12.15 

     没看懂啥意思 。。。

12.16 

   Max设置为一个不可能的数,比如2^16-1  

  min设置为-1 

  好处: 相当于深度多1,不够时可以用后面的位置,判断条件可以简化(应该?)

12.17

   完全d叉树(总)

    ⚠️:推论看第十一章    

#include<iostream>
#include<queue>
#include<string>
using namespace std;
class Empty{
     private:
      string message;
    public:
      Empty(string str="The number of elements is 0") ;
      string what(){return message;}
};
template<class T>
class maxDHeap{//大根堆一定是一个完全二叉树  用数组表示
  
  public:
      maxDHeap(int init=20,int D=2);
     // ~maxDHeap(){delete [] heap;}
      ~maxDHeap(){;}//init初始化已有的数组不用释放
      void push(const T& theElement);
      void pop();
      void initialize(T* theHeap,int theSize);//初始化一个非空大根堆 传进去一个没排序好的
      void show();
       int maxChild(int leaf);//传进去的是根序号,返回最大孩子序号
       int findFather(int child);//返回父节点序号
       void changeMax(const T& theElement);
     private:
      T* heap;
      int heapSize;
      int arrayLength;
      int D;
};
template<class T>
maxDHeap<T>::maxDHeap(int init,int d){
     arrayLength=init;
   heap= new T[arrayLength];
   heapSize=0;
   D=d;
}
template<class T>
int
maxDHeap<T>::findFather(int child){
     int Leaf=child/D;

     if(Leaf*D+1<child)//定位到最后一个有孩子节点
          Leaf++;
        return Leaf;
}
template<class T>
int
maxDHeap<T>::maxChild(int leaf){
      int MaxNumber=leaf*D;//定位到第d-1个孩子
      int left=(leaf-1)*D+1;//左界限
     if(MaxNumber>heapSize)
         MaxNumber=heapSize;//没满
      
       for(int i=1;MaxNumber-i>left;i++){
              if(heap[MaxNumber]<heap[MaxNumber-i])
                   MaxNumber-=i;
       }
    if(leaf*D+1<=heapSize)
         if(heap[MaxNumber]<heap[leaf*D+1])//若有 则与第D个孩子比较
             return leaf*D+1;
        return
            MaxNumber;
        
     
}
template<class T>
void 
maxDHeap<T>::changeMax(const T& newElement){
          if(heapSize==0){
          cout<<"error!";
          exit(1);
      }
      int currentNode=1;
      int child=D;
    while(child<heapSize){
                if(newElement>=heap[child])
                  break;

              heap[currentNode]=heap[child];
               currentNode=child;
               child=maxChild(currentNode);  
    }
      heap[currentNode]=newElement;
}
template<class T>
void
maxDHeap<T>::initialize(T* theDheap,int theSize){
    delete [] heap;
          heap= theDheap;
          heapSize=theSize;
     //
       int lastLeaf;
       int Max;
       T temp;
     lastLeaf=findFather(heapSize);
    
      while(lastLeaf>=1){
           Max=maxChild(lastLeaf);
          cout<<Max<<" "<<endl;
          if(heap[lastLeaf]<heap[Max])
              swap(heap[lastLeaf],heap[Max]);//要解引用
            
            lastLeaf--;
      }
}
 
template<class T>
void
maxDHeap<T>::show(){//这个要改吗?
    
 queue<int> q;
 
 q.push(1);
  int current=1;
      while(!q.empty()){
         current=q.front();
         q.pop();
         cout<<heap[current]<<" ";
    
        if(current*2<=heapSize)//0
          q.push(current*2);
        if(current*2+1<=heapSize)
          q.push(current*2+1);
 
      }
    cout<<endl;
}
template<class T>
void 
maxDHeap<T>::pop(){
      if(heapSize==0){
          cout<<"error!";
          exit(1);
      }
       
    
    heap[1].~T();
 
    T lastElement= heap[heapSize--];
      int currentNode=1;
      int Max=maxChild(currentNode);//1*d
     
       while(Max<heapSize){
          //定位到最大的孩子
            if(lastElement>=heap[Max])
               break;
            
            heap[currentNode]=heap[Max];
            currentNode=Max;
             Max=maxChild(currentNode);
       }
            heap[currentNode]=lastElement;
}
template<class T>
void 
maxDHeap<T>::push(const T& theElement){
      if(heapSize==arrayLength-1){
            T* temp = new T[arrayLength*2];
        copy(heap+1,heap+arrayLength,temp+1);
        delete heap;
        heap=temp;
        arrayLength*=2;
      }
    int currentNode= ++heapSize;
    int fatherNode;
       while(currentNode!=1){
                fatherNode=findFather(currentNode);
                 if(heap[fatherNode]>=theElement)
                      break;
                heap[currentNode]=heap[fatherNode];
                currentNode=fatherNode;
                    
       }
            heap[currentNode]=theElement;

}
int main(){
    maxDHeap<int> a(20,3);
   int heap[20]={0,4,7,9,12,1,6};
    a.initialize(heap,6);
    a.show();
    a.changeMax(5);
    a.show();
   return 0;

}

  性能 : 分别进行两千次pop 和随机push操作   

     

int main(){
    maxDHeap<int> x1(20,4);
    maxHeap<int>  x2(20);
    int heap[20]={0,20,12,35,15,10,80,30,17,2,1};//从1 开始 统一
    x2.initialize(heap,10);
    x1.initialize(heap,10);
    
    srand(1);
    
   long double clocksPerMillis = double(CLOCKS_PER_SEC) /1000;  //CLOCKS 是滴答数的一秒 、除以1k 就是一毫秒的滴答数字
      
            
             clock_t startTimeX1= clock();//返回目前为止的时间
          for(int i=1;i<2000;i++)
              x1.push(rand()%65536);
            for(int i=1;i<2000;i++)
               x1.pop();
          long double elapsedMillisX1= (clock()-startTimeX1)/clocksPerMillis;
             
             clock_t startTimeX2= clock();//返回目前为止的时间
          for(int i=1;i<2000;i++)
              x2.push(rand()%65536);
            for(int i=1;i<2000;i++)
               x2.pop();
          long double elapsedMillisX2= (clock()-startTimeX2)/clocksPerMillis;

           cout<<"maxDheap:"<< elapsedMillisX1<<" "<<"maxHeap:"<<elapsedMillisX2<<endl;
        
        
    return 0;
}

   结果当D分别为2,3,4时 

        

 可见随着度的增加效率并没有提高,反而降低了 ,并不是越多越好

  虽然高度降低了,但查找,判断的成本增高了,还要反复调用函数  

12.18 

    见chengeMax

12.19 -20

     左高大根树(maxHblt

      

#include<iostream>
#include<queue>// 队列 
#include<stack>
using namespace std;
template<class T>
struct binaryTreeNode{
     T element;
     binaryTreeNode<T> *leftChild,*rightChild;//三个域
 
     //三个构造
     binaryTreeNode(){leftChild=rightChild=NULL;}
     binaryTreeNode(const T& theElement){element=theElement;}
     binaryTreeNode(const T& theElement,binaryTreeNode<T> *left,binaryTreeNode<T> *right){
            element=theElement;
            leftChild=left;
            rightChild=right;
     }
 
};
template<class T>
class maxHblt{
    public:
     
     void meld(maxHblt<T> & theMaxHblt);//都是以此为基础
     void initialize(T* theElement,int theSize);
     void push(const T& theElement);
     void pop();
     void show();
     
 
    private:
     binaryTreeNode< pair<int,T>  > *Root;
     int Size;
     void meld(binaryTreeNode<pair<int,T> >* &x,binaryTreeNode<pair<int,T> >* &y);//pair第一个是s(x) 
     
 
};
template<class T>
void
maxHblt<T>::show(){
    queue< binaryTreeNode<pair<int,T> > * > q;
    binaryTreeNode<pair<int,T> > * current;
 
 q.push(Root);
      while(!q.empty()){
         current=q.front();
         q.pop();
         cout<<current->element.second<<" ";
        if(current->leftChild!=NULL)//0
          q.push(current->leftChild);
        if(current->rightChild!=NULL)
          q.push(current->rightChild);
 
      }
    cout<<endl;
}
template<class T>
void
maxHblt<T>::meld(binaryTreeNode<pair<int,T> >* &x,binaryTreeNode<pair<int,T> >* &y){
//默认以x为根 不行则交换 
   if(y==NULL)
       return ;
     if(x==NULL){
          x=y; return ;
     }
       if(x->element.second< y->element.second)//保证大根
         swap(x,y);
     meld(x->rightChild,y);
   //执行到此说明 已经递归到底了  x指向最右内部节点 
       if(x->leftChild==NULL){
            x->leftChild=x->rightChild;
            x->rightChild=NULL;
            x->element.first=1;
       }
    else{
        if(x->leftChild->element.first<x->rightChild->element.first)
           swap(x->rightChild,x->leftChild);
         
         x->element.first=x->rightChild->element.first+1;
    }
     
}
template<class T>
void
maxHblt<T>::meld(maxHblt<T>& theHblt){
     meld(Root,theHblt.Root);
    Size+=theHblt.Size;
    theHblt.Root=NULL;
    theHblt.Size=0;
}
template<class T>
void
maxHblt<T>::push(const T& theElement){
    binaryTreeNode<pair<int,T> > *q= new  binaryTreeNode<pair<int,T> >(pair<int,T>(1,theElement));

    meld(Root,q);
    Size++;
}
template<class T>
void
maxHblt<T>::pop(){
    if(Root==NULL){
         cout<<"empty!"<<endl;
         exit (1);
    }
     binaryTreeNode<pair<int,T> > * left=Root->leftChild, *right= Root->rightChild;
     delete Root;
     Root=left;
     meld(left,right);
     Size--;
}
template<class T>
void
maxHblt<T>::initialize(T* theElement,int theSize){
    queue< binaryTreeNode<pair<int,T> > * > q;
     binaryTreeNode<pair<int,T> > *a,*b;
    //erase();
    for( int i=1;i<=theSize;i++){
      q.push( new  binaryTreeNode<pair<int,T> >(pair<int,T>(1,theElement[i])) ) ;//全算单子树加入
    }
     for(int i=1;i<theSize;i++){
         a=q.front();
         q.pop();
         b=q.front();
         q.pop();
         meld(a,b);
         q.push(a); 
     }

     Root=q.front();
    Size=theSize;
    
}
int main(){
    int heap[]={-1,3,5,6,7,20,8,2,9,12,15,30,17};
     maxHblt<int> a;
    a.initialize(heap,12);
    a.show();
    return 0;
}

12.21

      判断改一下就行了

 if(x->element.second> y->element.second)//保证大根
         swap(x,y);

12.22

 buhui

12.23  

     另外meld需要改 father指针也要 

template<class T>
struct binaryTreeNode{
     T element;
     binaryTreeNode<T> *leftChild,*rightChild,*fatherNode;//三个域
 
     //三个构造
     binaryTreeNode(){fatherNode= leftChild=rightChild=NULL;}
     binaryTreeNode(const T& theElement){element=theElement;}
     binaryTreeNode(const T& theElement,binaryTreeNode<T> *left,binaryTreeNode<T> *right,binaryTreeNode<T> *father){
            element=theElement;
            leftChild=left;
            rightChild=right;
            fatherNode=father;
     }
 
};
template<class T>
class maxWithRemoveNodeWithRemoveNode{
    public:
     
     void meld(maxWithRemoveNodeWithRemoveNode<T> & themaxWithRemoveNodeWithRemoveNode);//都是以此为基础
     void initialize(T* theElement,int theSize);
     void push(const T& theElement);
     void pop();
     void show();
     //12.23
     binaryTreeNode<pair<int,T> >* pushAndReturnNode(const T& theElement);
     T removeElementInNode(binaryTreeNode<pair<int,T> >* theNode);
 
    private:
     binaryTreeNode< pair<int,T>  > *Root;
     int Size;
     void meld(binaryTreeNode<pair<int,T> >* &x,binaryTreeNode<pair<int,T> >* &y);//pair第一个是s(x) 
     
 
};
template<class T>
binaryTreeNode<pair<int,T> >*
maxWithRemoveNodeWithRemoveNode<T>::pushAndReturnNode(const T& theElement){
     binaryTreeNode<pair<int,T> > *x= new  binaryTreeNode<pair<int,T> >(pair<int,T>(1,theElement)),*result=NULL,*current=NULL,*temp=Root;
    
        while(temp!=NULL){//定位
              if(temp->element.second < theElement)
                break;
            current=temp;
            temp=temp->rightChild;
        }
          result=current;
        meld(current,x);
       if(result->leftChild->element==theElement)//右边可能为空
          return result->leftChild;
    return result->rightChild;
        
}
template<class T>
T
maxWithRemoveNodeWithRemoveNode<T>::removeElementInNode(binaryTreeNode<pair<int,T> >* theNode){
      // 有父节点就不用遍历
        T result =theNode->element.second;
        binaryTreeNode<pair<int,T> > *l=theNode->leftChild,*r=theNode->rightChild;
        meld(l,r);
        meld(theNode->fatherNode,l);
        return result;

}

12.24.  

   1) 没有12.1呀?

   2)  当w(x)= 1时显然成立 

                          =2 时必然在左边

                          =3 时才是满树 此时 最右路径为2 成立 

         -->定义为左重 是颗完全树

            看定理12-1 第二点 同证明

   

#include<iostream>
#include<queue>// 队列 
#include<stack>
using namespace std;
template<class T>
struct binaryTreeNode{
     T element;
     binaryTreeNode<T> *leftChild,*rightChild;//三个域
 
     //三个构造
     binaryTreeNode(){leftChild=rightChild=NULL;}
     binaryTreeNode(const T& theElement){element=theElement;}
     binaryTreeNode(const T& theElement,binaryTreeNode<T> *left,binaryTreeNode<T> *right){
            element=theElement;
            leftChild=left;
            rightChild=right;
     }
 
};
template<class T>
class maxWblt{
    public:
     
     void meld(maxWblt<T> & themaxWblt);//都是以此为基础
     void initialize(T* theElement,int theSize);
     void push(const T& theElement);
     void pop();
     void show();
     
 
    private:
     binaryTreeNode< pair<int,T>  > *Root;
     int Size;
     void meld(binaryTreeNode<pair<int,T> >* &x,binaryTreeNode<pair<int,T> >* &y);//pair第一个是s(x) 
     
 
};
template<class T>
void
maxWblt<T>::show(){
    queue< binaryTreeNode<pair<int,T> > * > q;
    binaryTreeNode<pair<int,T> > * current;
 
 q.push(Root);
      while(!q.empty()){
         current=q.front();
         q.pop();
         cout<<current->element.second<<" ";
        if(current->leftChild!=NULL)//0
          q.push(current->leftChild);
        if(current->rightChild!=NULL)
          q.push(current->rightChild);
 
      }
    cout<<endl;
}
template<class T>
void
maxWblt<T>::meld(binaryTreeNode<pair<int,T> >* &x,binaryTreeNode<pair<int,T> >* &y){
//默认以x为根 不行则交换 
   if(y==NULL)
       return ;
     if(x==NULL){
          x=y; return ;
     }
       if(x->element.second< y->element.second)//保证大根
         swap(x,y);
     meld(x->rightChild,y);
   //执行到此说明 已经递归到底了  x指向最右内部节点 
       if(x->leftChild==NULL){
            x->leftChild=x->rightChild;
            x->rightChild=NULL;
            x->element.first=1;
       }
    else{
        if(x->leftChild->element.first<x->rightChild->element.first)
           swap(x->rightChild,x->leftChild);
         
         x->element.first=x->rightChild->element.first+1+x->leftChild->element.first;//1这里改为加左右孩子
    }
     
}
template<class T>
void
maxWblt<T>::meld(maxWblt<T>& theHblt){
     meld(Root,theHblt.Root);
    Size+=theHblt.Size;
    theHblt.Root=NULL;
    theHblt.Size=0;
}
template<class T>
void
maxWblt<T>::push(const T& theElement){
    binaryTreeNode<pair<int,T> > *q= new  binaryTreeNode<pair<int,T> >(pair<int,T>(1,theElement));

    meld(Root,q);
    Size++;
}
template<class T>
void
maxWblt<T>::pop(){
    if(Root==NULL){
         cout<<"empty!"<<endl;
         exit (1);
    }
     binaryTreeNode<pair<int,T> > * left=Root->leftChild, *right= Root->rightChild;
     delete Root;
     Root=left;
     meld(left,right);
     Size--;
}
template<class T>
void
maxWblt<T>::initialize(T* theElement,int theSize){
    queue< binaryTreeNode<pair<int,T> > * > q;
     binaryTreeNode<pair<int,T> > *a,*b;
    //erase();
    for( int i=1;i<=theSize;i++){
      q.push( new  binaryTreeNode<pair<int,T> >(pair<int,T>(1,theElement[i])) ) ;//全算单子树加入
    }
     for(int i=1;i<theSize;i++){
         a=q.front();
         q.pop();
         b=q.front();
         q.pop();
         meld(a,b);
         q.push(a); 
     }

     Root=q.front();
    Size=theSize;
    //cout<<Root->element.first<<endl;
    
}
int main(){
    int heap[]={-1,3,5,6,7,20,8,2,9,12,15,30,17};
     maxWblt<int> a;
    a.initialize(heap,12);
    a.show();
    return 0;
}

        非递归meld待写:

                        a. 调用后序遍历 

                        b.怎么插入的位置往上都需要改w  ,增加一个父节点指针?

(1条消息) C++(数据结构与算法):42---优先级队列的实现(扩充二叉树、高度优先左高树(HBLT)、重量优先左高树(WBLT))_董哥的黑板报-CSDN博客

4)

 大根堆

    用堆实现优先级队列的空间利用率很高,而且效率也很高,但是并不适用于所有优先级队列,尤  其当两个优先级队列或多个长度不同的队列需要合并的时候,这时就需要其他的数据结构了,左高 树就能满足这种需要
    堆与左高树的异同
WBLT、HBLT可以执行优先级队列的查找、插入、删除操作,时间复杂度与堆相同
WBLT、HBLT和堆一样,可以在线性时间内完成初始化
用WBLT、HBLT表示的两个优先级队列可以在对数时间内合并为一个,而桶堆表示的优先级队列却不行

   总的来说 当需要特殊操作时,大根堆并不支持

 12.25

   感觉,只是判断条件变了

12.26-27 

      
 

12.28  

   d不是越多越好 ,取二的时候应该最好

12.29

    没写,没想到pop改进方法

12.30

  堆排序不是稳定的 ,因为是靠节点层移动的

  插入排序是稳定的,是一个一个比较移动插入

12.31-32

    

12.33

  因为element+= 了 所以必然往下移动 ,上面就不用做多余的比较了 ,只需要从此位置往下比较插入 就行了 不用从root比较 

12.34-35 

  如12题的 

12.36 

    maxHeap 添加两个成员函数 

     

 void load(T size);//按worst fit rule 装入
      maxHeap(int init,int c);//初始化 capacity

    

template<class T>
void 
maxHeap<T>::load(T size){
  if(size>capacity){
      cout<<"Greater than capacity"<<endl;
       exit(1);
  }
    int current  =1,child=2;
if(heap==NULL){
     heap[++heapSize]=capacity-size;
}
 else 
   if( heap[1]>=size ){
       int temp=  heap[1]-size;
        while(child<heapSize){
              if(heap[child]<heap[child+1])
                      child++;
        
           if(temp>heap[child])
               break;
            heap[current]=heap[child];
            current=child;
            child*=2;
        }
          heap[current]= temp;
   }
   else {
            push(capacity-size);
   }
        
}
template<class T>
maxHeap<T>::maxHeap(int init){
         heap = new T[init+1];//从1开始
    arrayLength=init+1;
    heapSize=0;
}
template<class T>
maxHeap<T>::maxHeap(int init,int c){
     heap=new T[init];
     arrayLength=init;
     heapSize=0;
     capacity=c;
}

12.37-38 

    

   

12.39

   两个归并段就相当于合并两个有序数组,每一个归并段相当于一个节点,权值相当于长度

构建霍夫曼树

   因为任意两个时间复杂度O(i+j) 

   用霍夫曼树总权值就最小,符合期望

12.40 

      权重越大编码越短 

      霍夫曼树总代码(0)

              

#include <iostream>
#define DefaultSize 10
template<class T>
class huffmanNode{
    huffmanNode(){weight=0; element=0; left=right=NULL;}
      huffmanNode<T> *left,*right;

      T weight;//权值 ,频率 
      T element;//字符 外部节点为字符,内部为0
      
};
template<class T>
class huffmanTree{
   public:
     huffmanTree();
     ~huffmanTree(){;}
     void initHuffmanTree(T *weight,int n);//输入权值,返回一颗霍夫曼树,利用小根堆
     void OutputCodingTable();


   private:
    huffmanNode<T> * Root;
    int TreeSize;

};

     小根堆  初始化:

1)

    

2)

   比率是1 因为都是频率大的路径短

3)

   跟左偏树一样: n个内节点,有n+1个外节点-->可以创建一个有n-1个节点右偏数然后中序遍历插入

4)-6)

  初始化都是O(n) 不推荐用右偏树,复杂还要写meld 

12.41

     证明: 假设一个棵树是最小WEP ,存在一颗子树,拥有两个最小频率

--> a.   两个最小频率一定是兄弟 ,所以到这两个外节点的路径长度L相同 

    所以删除这个两个外节点,子根(权F为两个最小频率之和)为单节点,WEP=L * F 

只会L减少,F不会变 所以仍为最优树

     

12.42-44

 0 赶时间 代补

 用前序遍历输出编码

     霍夫曼编码 - Roy_Mustango - 博客园

                                                          第十二章总结

本章主要讲了优先级队列 

  方法

  a  无序表/有序表:要么查找要时间,要么插入要时间

  b   大根堆/小根堆(隐式的结构,数组代替指针):使最大最小的永远在root

       但不容易实现其他操作(如合并)->

  c    左高树/重高树: s(x) 内外节点  

        MaxHblt 和MaxWblt 主要靠meld

 应用

     利用大根堆来排序: O(nlongn)

    机器调度 NP问题:  LPT算法

     

 霍夫曼编码:  按照频率分配代码长短(不定长)利用小根队来初始化  

     是一种前缀不相同的编码 (0 左 1右)

         OKOK-- 21/11/17

 

     

    

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值