堆排序以及优先队列

算法导论中的堆排序。
主要的几个函数:

三个宏用来表示取父节点和左右子节点,算法导论讲的很详细实现很简单
#define PARENT(i)(i/2)
#define  LEFT(i)(2*i)
#define  RIGHT(i)(2*i+1)
class Numbersort
{
public:
    Numbersort()
    {
        arry=NULL;
        nmber=0;
    }
    ~Numbersort()
    {
        if (arry!=NULL)
        {
            delete[]arry;
        }
    }

    int copynumber(int *p,int n);//给arry赋值
    void putout();///输出数组
    void sortnumber();///顺序排序,检验排序的正确性,堆排序中不用
    void max_heapify(int heap_size,int i);//对长度为heap_size的堆的节点进行最大堆排序,以维护当前节点以及子节点的最大堆性质
    void build_max_heap();//调用max_heapify构建最大堆
    void stack_sort();//对build_max_heap()构建好的最大堆进行排序
    void increase_key(int i,int key);//将当前借点i的key增加key(不是增加到key)
    void addnum(int newn);//增加newn到最大堆中


private:
    int *arry;
    int nmber;
    int size_down;
};
函数int copynumber(int *p,int n)、void putout()和sortnumber()没啥好说的。
void Numbersort::max_heapify(int heap_size,int i)
{
    int l=LEFT(i);
    int r=RIGHT(i);
    int largest=0;
    //堆排序的顺序比在数组中的位置大1,所以排序的顺序都要减去1
    if (l<=heap_size&&arry[l-1]>arry[i-1])
    {
        largest=l;

    }
    else
        largest=i;
    if (r<=heap_size&&arry[r-1]>arry[largest-1])
    {
        largest=r;
    }
    if (largest !=i)
    {
        int temp=arry[largest-1];
        arry[largest-1]=arry[i-1];
        arry[i-1]=temp;
        max_heapify(heap_size,largest);//递归调用以保证父节点后的子节点是最大堆
    }
}
void Numbersort::build_max_heap()
{
    int heap_size=nmber;
    int half_size=heap_size/2;//最大堆中的去掉叶节点的节点数
    for (int i=half_size;i>0;i--)
    {
        max_heapify(nmber,i);//对每个父节点逐次调用最大堆

    }
}
void Numbersort::stack_sort()
{

    for (int i=size_down;i>1;i--)
    {
        int temp=arry[0];
        int temp2=arry[i-1];
        arry[i-1]=arry[0];
        arry[0]=temp2;//将最大的arry[0]与还未排序的最后一个交换,则最后一个就排好了数
        size_down--;//sizedown减1后,已经排序好的数就不再参与最大堆排序。
        max_heapify(size_down,1);
        putout();
    }
}

addnum(int newn)将一个newn元素添加到末尾,然后

void Numbersort::addnum(int newn)
{
    int *p=new int [++nmber];

    for (int i=0;i<nmber-1;i++)
    {
        p[i]=arry[i];
    }
    if (arry!=NULL)
    {
        delete arry;
        arry=new int[nmber];
        for (int i=0;i<nmber-1;i++)
        {
            arry[i]=p[i];
        }
        delete p;
    }
    arry[nmber-1]=0;//将最后一个元素置为0,然后调用increase_key
    increase_key(nmber,newn);
}

将最大堆的第i个元素增加key

void Numbersort::increase_key(int i,int key)
{

    arry[i-1]+=key;
    while(i>1&&arry[PARENT(i)-1]<arry[i-1])
    {//如果父节点比子节点小,则交换数,再对父节点进行判断,递归父节点的父节点是否符合。
        int temp=arry[PARENT(i)-1];
        arry[PARENT(i)-1]=arry[i-1];
        arry[i-1]=temp;
        i=PARENT(i);
    }
}

总结:算法很简单,但是实现的时候总是会出现一些小问题,解决的也很爽快,主要还是不够细心,没有在草稿纸上先画一下。
有时候感觉,算法都贴出来有点傻X,这么简单还贴。这是一种小小成就感在内心蒸腾~(-ิo-ิ)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值