最大-最小堆

/**收获及心得


1.熟悉了二叉堆的class,并将其改为了升级版的最大-最小二叉堆
2.学会了声明,定义以及使用友元
3.对vector有了更深的理解
4.percolate down函数的算法断断续续写了四五天才大概满足次二叉堆的性质,收获蛮多
5.至于本次程序是为完成书上P187 6.18的练习题


***遗留下的问题
1.merge函数还未完成,主要还未了解merge过程
2.本想尝试写一个抛出异常的类来解决,堆为空的情况,最后一exit代替
3.关于屏幕上的移动光标的问题,本想直接生成一个树的形状,曾考虑用数组来实现,
不过感觉其意义不大,有空试试能否直接移动光标来实现
4.总感觉percolate down函数写的有点拖沓,不如书上二叉堆的来的简洁


                                                                5.22~5.29

*/


第一部分 老样子 最大最小堆的类

#ifndef BINARYHEAP_H
#define BINARYHEAP_H


#include<vector>
#include<iostream>


using namespace std;


class BinaryHeap
{
    public:
        BinaryHeap();
        virtual ~BinaryHeap();
        BinaryHeap(const vector<int> &items);


        const int &findMin() const;
        const int &findMax() const;
        void insert(const int &x);
        void deleteMin();
        void deleteMin(int &minItem);
        void deleteMax();
        void deleteMax(int &maxItem);
        void print() const;


    private:
        int current_size;
        vector<int> array;
        void build_heap();
        void percolateDown(int hole);
        bool isEmpty() const;
        void makeEmpty();


        friend int findMax_grandson(BinaryHeap&H,int hole);
        friend int findMin_grandson(BinaryHeap&H,int hole);
};


#endif // BINARYHEAP_H



第二部分为上头文件相关函数的具体定义

#include "..\include\BinaryHeap.h"


#include<cmath>
#include<cstdlib>
#include<iostream>


using namespace std;




BinaryHeap::BinaryHeap()//default constructor
{
    array.resize(100);
    current_size=0;
}


BinaryHeap::~BinaryHeap()
{
    makeEmpty();
}


BinaryHeap::BinaryHeap(const vector<int>&items)//copy constructor
    :array(items.size()+10),current_size(items.size())
{
    for(unsigned i=0;i<items.size();i++)
        array[i+1]=items[i];
    build_heap();
}


void BinaryHeap::insert(const int &x)
{
    if(current_size==array.size()-1)
        array.resize(array.size()*2);
    int hole=++current_size;
    int depth=log(hole)/log(2);




    while(depth>1)
    {
        if(depth/2==0)//percolate up in even depth
        {
            if(x<array[hole/2]&&x<array[hole/4])
            {
                array[hole]=array[hole/4];
                hole=hole/4;
                depth-=2;
            }
            else if(x>array[hole/2]&&x>array[hole/4])
            {
                array[hole]=array[hole/2];
                hole=hole/2;
                depth-=1;
            }
            else return;//the hole is at the right position,accord with the rule of min_max binaryheap
        }
        else//percolate up in odd depth
        {
            if(x>array[hole/2]&&x>array[hole/4])
            {
                array[hole]=array[hole/4];
                hole=hole/4;
                depth-=2;
            }
            else if(x<array[hole/2]&&x<array[hole/4])
            {
                array[hole]=array[hole/2];
                hole=hole/2;
                depth-=1;
            }
            else return;//the same as above
        }
    }




    if(depth==1&&array[hole/2]>x)//only two storeys
    {
        array[hole]=array[hole/2];
        hole=hole/2;
    }
    array[hole]=x;
}




void BinaryHeap::print() const//print this heap
{
    cout<<"**************************************************"<<endl;
    for(int i=1;i<=current_size;i++)
        cout<<array[i]<<"  ";
    cout<<endl;


}




void BinaryHeap::deleteMin()
{
    if(isEmpty())
        {
            cerr<<"Error!!This heap is empty!"<<endl;
            exit(1);//if having time,making a throw exception
        }
    array[1]=array[current_size--];
    percolateDown(1);
}






void BinaryHeap::deleteMin(int &minItem)
{
    if(isEmpty())
        {
            cerr<<"Error!!This heap is empty!"<<endl;
            exit(1);
        }
    minItem=array[1];//using minItem to record the minimum
    array[1]=array[current_size--];
    percolateDown(1);
}




void BinaryHeap::deleteMax()
{
    if(isEmpty())
        {
            cerr<<"Error!!This heap is empty!!"<<endl;
            exit(1);
        }
    else if(current_size==1)    current_size--;
    else if(current_size==2)    current_size--;
    else
    {
        if(array[3]>array[2])
        {
            array[3]=array[current_size--];
            percolateDown(3);
        }
        else
        {
            array[2]=array[current_size--];
            percolateDown(2);
        }
    }


}




void BinaryHeap::deleteMax(int &maxItem)
{
    if(isEmpty())
        {
            cerr<<"Error!!This heap is empty!!"<<endl;
            exit(1);
        }


    //using maxItem to record the maximum
    else if(current_size==1)    {maxItem=array[1];current_size--;}
    else if(current_size==2)    {maxItem=array[2];current_size--;}
    else
    {
        if(array[3]>array[2])
        {
            maxItem=array[3];
            array[3]=array[current_size--];
            percolateDown(3);
        }
        else
        {
            maxItem=array[2];
            array[2]=array[current_size--];
            percolateDown(2);
        }
    }


}


bool BinaryHeap::isEmpty() const
{
    if(current_size==0)
        return true;
    return false;
}




const int& BinaryHeap::findMin() const
{
    if(isEmpty())
        {
            cerr<<"Error!! this binaryheap is empty!!"<<endl;
            exit(1);
        }
    return array[1];
}




const int& BinaryHeap::findMax() const//find the maximum
{
    if(isEmpty())
    {
        cerr<<"Error!!This binaryheap is empty!!"<<endl;
        exit(1);
    }
    else if(current_size==1)
        return array[1];
    else if(current_size==2)
        return array[2];
    else
    {
        if(array[2]<array[3])
            return array[3];
        return array[2];
    }
}




void BinaryHeap::makeEmpty()
{
    array.clear();//clear the array
    current_size=0;
}






void BinaryHeap::percolateDown(int hole)//the most importment algorithm of this binaryheap
{
    int now_depth=log(hole)/log(2);
    int depth=log(current_size)/log(2);
    int child;
    int grandson;
    int tmp=array[hole];


    if(now_depth%2==1)//when at odd depth,percolate down
    {
         while(depth-now_depth>=2)
        {
            child=2*hole;
            if(array[child+1]>array[child])     child++;


            if(current_size>=4*hole)
                grandson=findMax_grandson(*this,hole);
            else    break;//having no grandson,but maybe depth-now_depth=2


            //if do nothing at the two judgements below,the hole is in the right position
            if(tmp>=array[child]&&tmp>=array[grandson])     return;


            if(tmp<array[child])//pay attention to the value of hole,it does not change!!
            {
                array[hole]=array[child];
                array[child]=tmp;
                tmp=array[hole];
            }


            if(tmp<array[grandson])//change the hole at this point
            {
                array[hole]=array[grandson];
                array[grandson]=tmp;
                hole=grandson;
                tmp=array[hole];
            }
            else    {hole=grandson; tmp=array[hole];}




            now_depth+=2;//percolate down 2 depths
        }
        if(depth-now_depth==2)//end the loop from the break above
        {
            child=2*hole;
            if(array[child+1]>array[child]) child++;
            if(array[hole]<array[child])
            {
                tmp=array[hole];
                array[hole]=array[child];
                array[child]=tmp;
            }
        }


        if(depth-now_depth==1)//only 2 storeys
        {
            child=2*hole;
            if(current_size>child&&array[child+1]>array[child]) child++;
            if(child<=current_size&&array[child]>array[tmp])//exchange hole with the bigger child
            {
                tmp=array[hole];
                array[hole]=array[child];
                array[child]=tmp;
            }
        }
    }


    else//when the hole at even depth
    {
         while(depth-now_depth>=2)
        {
            tmp=array[hole];
            child=2*hole;
            if(array[child+1]<array[child])     child++;


            if(current_size>=4*hole)
                grandson=findMin_grandson(*this,hole);
            else    break;


            //if do nothing at the two judgements below,the hole is in the right position
            if(tmp<=array[grandson]&&tmp<=array[child])     return;


            if(tmp>array[child])//pay attention to the hole,the same as above
            {
                array[hole]=array[child];
                array[child]=tmp;
                tmp=array[hole];
            }


            if(tmp>array[grandson])
            {
                array[hole]=array[grandson];
                array[grandson]=tmp;
                hole=grandson;
                tmp=array[hole];
            }
            else    {hole=grandson;     tmp=array[hole];}


            now_depth+=2;//percolatedown 2 depths
        }


         if(depth-now_depth==2)//end the loop from the break above
        {
            child=2*hole;
            if(array[child+1]>array[child]) child++;
            if(array[hole]>array[child])
            {
                tmp=array[hole];
                array[hole]=array[child];
                array[child]=tmp;
            }
        }


        if(depth-now_depth==1)
        {
            child=2*hole;
            if(current_size>child&&array[child+1]<array[child]) child++;
            if(child<=current_size&&array[child]<array[hole])
            {   tmp=array[hole];
                array[hole]=array[child];
                array[child]=tmp;
            }
        }
    }


}


void BinaryHeap::build_heap()
{
    for(int i=current_size/2;i>0;i--)
        percolateDown(i);
}




//the declaration of the friend functions
int findMin_grandson(BinaryHeap&H,int hole)//finding the position of minimal grandson
{
    int grandson=4*hole;
    if(grandson==H.current_size)  ;
    else if(grandson+1==H.current_size)
    {
        if(H.array[H.current_size]<H.array[grandson])  grandson++;
        else    ;
    }
    else if(grandson+2==H.current_size)
        {
            for(int i=grandson;i<4*hole+3;i++)
            {
                grandson=H.array[grandson]<H.array[i]?grandson:i;
            }
        }
    else
    {
       for(int i=grandson;i<4*hole+4;i++)
       grandson=H.array[grandson]<H.array[i]?grandson:i;


    }


    return grandson;




}




int findMax_grandson(BinaryHeap&H,int hole)//finding the position of maximal grandson
{
    int grandson=4*hole;
    if(grandson==H.current_size)  ;
    else if(grandson+1==H.current_size)
    {
        if(H.array[H.current_size]>H.array[grandson])  grandson++;
        else    ;
    }
    else if(grandson+2==H.current_size)
        {
            for(int i=grandson;i<4*hole+3;i++)
            {
                grandson=H.array[grandson]>H.array[i]?grandson:i;
            }
        }
    else
    {
       for(int i=grandson;i<4*hole+4;i++)
        grandson=H.array[grandson]>H.array[i]?grandson:i;


    }


    return grandson;
}


第三部分 为类的测试

#include <iostream>
#include"include/BinaryHeap.h"


using namespace std;


int main()//symble checking
{


    vector<int>aa;
    for(int i=12;i>0;i--)
        aa.push_back(i);
    BinaryHeap H(aa);
    H.print();
    H.deleteMax();


    H.print();
    H.insert(16);
    H.print();
    cout<<H.findMax()<<endl;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值