数据结构----优先级队列

优先级队列: 基于大根堆和小根堆实现

设初始序列为:(49,38,65,97,76)

①大根堆:父节点的值大于或等于子节点的值(令数值越大优先级越高)
在这里插入图片描述
    此时堆顶的元素为所有元素的最大值(97)
②小根堆:父节点的值小于或等于子节点的值(令数值越小优先级越高)
在这里插入图片描述
   此时堆顶的元素为所有元素的最小值(38)

  1. 将队列中的所有元素按从大到小的数值输出:
    ①分析: 因为队列是先进先出,后进后出,所以每次出队的为队头元素即堆顶元素queue【0】==>基于大根堆实现;
    ②思路如下:
    1>将入队的元素进行上浮操作,将最大值放置到堆顶(剩下的数没有顺序)
public void siftUp(int i,T val) {       //队尾插入元素
        while (i > 0) {     //当到堆顶时跳出循环
            int j=(i-1)/2;        //此时j指向的是i的父节点
            if (queue[j].compareTo(val) < 0) {       
                queue[i] = queue[j];            //如果插入元素大于父节点元素,并将父节点的值放置到i处
                i=j;                                      //将i指向当前父节点,在往上进行比较
            } else {
                break;
            }
        }
        queue[i]=val;                  //此时找到val的合适插入位置
    }

   2>此时出队的元素(堆顶元素)则为所有值中的最大值,将queue【0】出队,接下来需要出第二小的元素,由于剩下的数据是没有顺序的,所以利用下沉函数将剩下数据中的最大值放至堆顶
   3>将队尾元素放置堆顶,并与其子节点进行比较,找出最大值放至父节点,并从最大值的位置继续往下找非叶子节点

 for (int j=2*i+1;j<index;j=2*j+1){
            //右孩子大于左孩子
            if (j+1<index&&queue[j+1].compareTo(queue[j])>0) {
                j++;                 //如果右孩子值大于左孩子
            }
            if (queue[j].compareTo(val)>0){       //将两者中的较大值与队尾val(此时val为堆顶元素)比较
                queue[i]=queue[j];
                i=j;
            }
            else{
                break;
            }
        }
        queue[i]=val;          //将val放置合适的位置

此时已经将最大值放置堆顶,出队元素为值第二大的数

  1. 将队列中的所有元素按从小到大的数值输出:
    与1相似,只需要调整优先级比较结果即可。(数值越小优先级越大)
用优先级队列解决:
   1.求一亿个整数里面,花费O(n)时间,找出前十小的数据?         
1. 问题分析:
           1. 先拿出前十个数入队,假设为一亿个整数中前十小的数据(A为其中的最大值)
           2. 因为要找出最小的数,所以需要淘汰大的数(有较小值入队时将最大值出队)。
              基于大根堆实现
           3. 然后把剩下的数依次入队。
              在入队前和 A 做比较
              如果入队的数 >= A,则肯定不为前十小,直接入下一个数
              若 < A ,则舍弃 A ,对新数进行入队操作
           4. 直至将最后一个数入队,最终剩下为前十小的数

相比较基于大根堆的优先级队列来说,解决此问题只需要在push()方法当放置元素下标越界时调用judge()函数进行上述操作 3

 public void judge(T val) {
        if (val.compareTo(queue[0]) >= 0) {  //如果新入队的数比前十小的树中最大的数都大(等于),则舍弃
            return;
        }
        // 若小于,则舍弃最大值,将新数值入队
        else {
            pop();
            push(val);
        }
    }

当一亿个整数都完成入队操作后,最终剩下的十个数为数组中前十小的数。
    2.求一亿个整数里面,花费O(n)时间,找出前十大的数据?

2. 问题分析:  1. 先拿出前十个数入队,假设为一亿个整数中前十大的数据(A为其中的最大值)
               2. 因为要找出最大的数,所以需要淘汰小的数(有较大值入队时将最小值出队)。
                  基于小根堆实现
               3. 然后把剩下的数依次入队。
                  在入队前和 A 做比较
                  如果入队的数 <= A,则肯定不为前十小,直接入下一个数
                  若 >A ,则舍弃 A ,对新数进行入队操作
               4. 直至将最后一个数入队,最终剩下为前十大的数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值