数据结构学习笔记(六)之 堆与优先队列

        理解:以数组为结构,更方便查找数据上下级之间的联系用下标的数学关系表示,增删也只需要组内交换数据即可,排序看似有两条路线,还包括一个上级,但实际上,同级、上级和自己并无关系,只有上级对下级单方面存在大小关系,所以数据改变之后只需要对往下的数据进行修改,往下的数据也只需要对符合条件的下级修改,另一个下级不用管,所以每次排序实际上只是对当前位置往下的一条线进行了交换排序

        概念:一种数据关系,一个上级与两个下级之间的联系,每个下级又有两个下级,以此获得一种数据顺序,分为大顶堆和小顶堆,大小的区别是,每个堆的上级比下级大还是小

        实现:用数组按级储存,0是第一级,1,2是第二级,3,4,5,6是第三级......

        上级与下级之间的关系,(上级下标 * 2 + 1) 为第一个下级,+2为第二个下级

                                                (下级下标 - 1 / 2) 为它的上级

        操作:

                压入:把数据加入数组尾部,然后往上遍历,直到遇到比自己大的上级

                向下排序:以大顶或小顶为条件,把堆进行上级比下级大/小的排序

                                技巧:以堆尾的上级为起点,意思就是以每个小堆为单位进行排序,第一个小堆就是堆尾的小堆,然后不断向前排序,也就是排序每一个小堆,每一个上级也是它上级的下级

                                看代码:

                                

//大顶堆
//单个堆排序
void get_greatheap(int *heap, int idx, int len){
    int tmp = idx;            //上级
    int l = idx * 2 + 1;        //左下级
    int r = l + 1;                //右下级
    while(l < len){      //没有左下级代表没有下级,结束排序
        if(heap[tmp] < heap[l])        //上级先和左下级比较
            tmp = l;
        if(r < len && heap[tmp] < heap[r])    //如果存在右下级,再进行比较
            tmp = r;
        if(tmp == idx)     //如果以上比较后,上级都没有变化,说明上级最大,无需遍历,退出循环
            break;
        swap(heap[tmp], heap[idx]);    //将比较后的结果,最大的值和上级交换
        idx = tmp;                    //以交换后的下级为下一个上级继续遍历排序
        l = tmp * 2 + 1;                //更新左下级和右下级
        r = l + 1;
    }
    return ;
}
//以每个小堆为单位,以堆尾的小堆为起点,向堆首遍历排序
int i;
    for(i = (LEN - 2) / 2; i >= 0; --i){    //找到堆尾的上级,以堆尾的小堆为起点进行遍历排序,LEN - 1表示堆尾坐标,上级=(下级 - 1) / 2
        get_greatheap(heap, i, LEN);
    }

                弹出:把任一位置数据弹出后,将堆尾和弹出位置swap,以弹出数据的位置往下为一个堆,开始遍历,不断把下级数据往上提,重新排好当前的堆,下级数据被删除对上级数据没有影响,对分支更没有影响

优先队列

        概念:利用堆头数据一定是全堆最大数据的特点,形成一种全队最大的数据优先从队头出队,从队尾进队的队结构

        实现:在堆的基础上,不断将堆头和堆尾调换位置,然后减小堆长,也就是让堆尾的空间依次存储最大的数据,然后将新堆从堆头开始重新排序

看代码


for(int i = LEN - 1; i > 0; i--){
    swap(heap[0], heap[i]);    //交换堆尾和堆头
    get_greatheap(heap, 0, i);//从头开始对新堆排序,因为长度减小了,减小的那部分空间作为队尾依次存放每次堆的最大数据,也就是从大到小入队
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值