• 数据结构-二叉树(5)利用数组实现堆


    #define DefaultSize 10;
    
    template <class E>   //堆中存储的是一个记录的集合,并根据每个记录的关键码以最小堆序排序,在使用堆操作之前需要定义记录的结构类型,用E表示
    class MinHeap:public PQueue<E>{
        //最小堆类继承了最小优先级队列
    public:
        MinHeap(int sz=DefaultSize);
        MinHeap(E arr[],int n);
        ~MinHeap(){delete []heap};
        bool Insert(const E& x);
        bool RemoveMin(E& x);
        bool IsEmpty()const{return currentSize==0;}
        bool IsFull()const{return currentSize==maxHeapSize;}
        void MakeEmpty(){currentSize=0;}
    private:
        E *heap;
        int currentSize;
        int maxHeapSize;
        void siftDown(int start,int m);
        void siftUp(int start);
    }
    
    template <class T>
    MinHeap<E>::MinHeap(int sz=DefaultSize){
        maxHeapSize=(DefaultSize<sz)?sz:DefaultSize;
        heap=new E[maxHeapSize];
        if(heap==NULL){
            cerr<<"堆存储分配失败!"<<endl;
            exit(1);
        }
        currentSize=0;
    }
    
    template <class T>
    MinHeap<E>::MinHeap(E arr[],int n){   //复制构造函数,数组调整成堆
        maxHeapSize=(DefaultSize<n)?n:DefaultSize;  //取n和DefaultSize中比较大的一个作为最小堆的大小
        heap=new E[maxHeapSize];
        if(heap==NULL){
            cerr<<"堆分配存储失败!"<<endl;
            exit(1);
        }
        for(int i=0;i<n;i++) heap[i]=arr[i];
        currentSize=n;
        int currentPos=(currentSize-2)/2;     //找最初调整位置:最后分支结点(最后一个结点的父结点)
        while(currentPos>=0){                  //自底向上逐步扩大成堆
            siftDown(currentPos,currentSize-1);   //局部自上向下下滑调整
            currentPos--;        //再向前换一个分支结点
        }
    }
    
    template <class T>
    void MinHeap<E>::siftDown(int start,int m){
        //私有函数,从结点start开始到m为止,自上而下比较,如果子女的值小于父结点的值,则关键码小的上浮,继续向下层比较,这样将一个集合局部调整为最小堆
        int i=start,j=2*i+1;   //j指向i的左子女
        E temp=heap[i];
        while(j<=m){
            if(j<m && heap[j]>heap[j+1]) j++;   //让j指向两子女中的小者
            if(temp<=heap[j]) break;
            else{
                heap[i]=heap[j];
                i=j;
                j=2*j+1;
            }
        }
        heap[i]=temp;
    }
    
    template <class E>
    void MinHeap<E>::siftUp(int start){
        //私有函数:从结点start开始到结点0为止,自下而上比较,如果子女的值小于父结点的值则相互交换,这样将集合重新调整为最小堆,关键码比较符<=在E的类型中定义
        int j=start,i=(j-1)/2;   //j指向i的父结点
        E temp=heap[j];
        while(j>0){
            if(heap[i]<=temp)break;
            else{
                heap[j]=heap[i];
                j=i;
                i=(i-1)/2;
            }
        }
        heap[j]=temp;
    }
    
    template <class E>
    bool MinHeap<E>::Insert(const E& x){
        if(currentSize==maxHeapSize){
            cerr<<"Heap Full"<<endl;
            return false;
        }
        heap[currentSize]=x;
        siftUp(currentSize);    //向上调整
        currentSize++;
        return true;
    }
    
    template <class E>
    bool MinHeap<E>::RemoveMin(E &x){
        if(!currentSize){
            cout<<"Heap empty"<<endl;
            return false;
        }
        x=heap[0];
        heap[0]=heap[currentSize-1];
        currentSize--;
        siftDown(0,currentSize-1);
        return true;
    }
  • 相关阅读:
    poj 3669 Meteor Shower
    poj 3009 Curling 2.0
    poj 1979 Red and Black
    区间内素数的筛选
    九度oj 题目1347:孤岛连通工程
    poj 3723 Conscription
    poj 3255 Roadblocks
    Luogu P3975 [TJOI2015]弦论
    AT2165 Median Pyramid Hard 二分答案 脑洞题
    后缀自动机多图详解(代码实现)
  • 原文地址:https://www.cnblogs.com/yangyuliufeng/p/9448694.html
Copyright © 2020-2023  润新知