优先级队列(堆)

优先级队列

1、二叉树的顺序存储(数组保存二叉树结构,层序遍历放入数组);
已知双亲(parent)下标,左孩子下标(left)=2parent+1,右孩子(right)下标=2parent+2;
已知孩子(child)下标,则双亲(parent)下标=(child-1)/2;
2、堆(heap)
逻辑上是一颗完全二叉树
物理上存放在数组中
满足任意结点的值都大于其子树中结点的值,叫做大根堆;
反之则是小根堆。

作用:快速找集合中的最值

  1. 操作-向下调整
    前提:左右子树必须是一个堆
    说明:
    1、array代表存储堆的数组
    2、size代表数组中被视为堆数据的个数
    3、index代表要调整位置下标
    4、left代表index左孩子下标,right代表右孩子下标
    5、min代表index的最小孩子的下标
    过程(小堆):
    1、index 如果已经是叶子结点,则整个调整过程结束,即:
    1、判断index位置没有孩子
    2、因为堆是完全二叉树,没有左孩子就一定没有右孩子,所以判断是否有左孩子;
    3、因为堆的存储结构是数组,所以判断是否有左孩子即判断左孩子下标是否越界,lift>=size越界;
    **2、**确定left或right,谁是index的最小孩子min
    1、如果右孩子不存在,则min=left
    2、否则,比较array[left]和array[right]的大小,选择小的为min
    3、比较array[index]的值和array[min]的值,如果array[index]<=array[min],则满足堆的性质,调整结束
    4、否则,交换array[index]和array[min]的值
    5、然后因为min位置堆的性质可能被破坏,所以把min视作index,向下重复以上过程
    如:
    // 调整前
    int[] array = { 27,15,19,18,28,34,65,49,25,37 };
    // 调整后
    int[] array = { 15,18,19,25,28,34,65,49,27,37 };
    代码:
public static void shiftDown(int[] array,int size,int index){
     int left=2*index+1;
     while(left<size){
         int min=left;
         int right=2*index+2;
         if(right<size){
            if(array[right]<array[left]){
            min=right;
         }
         
         if(array[index]<=array[min]){
            break;
         }
         
         int t=array[index];
         array[index]=array[min];
         array[min]=t;
         index=min;
         left=2*index+1;
       }
    }
      **3**、建堆
      大堆为例:
      //建堆前
      int[] array={1,5,3,8,7,6};
      //建堆后
      int[] array={8,7,6,5,1,3}
      代码:
public static void creatHeap(int[] array,int size){
     for(int i=(size-1-1)/2;i>=0;i--){
         shiftDown(array,size,i);
         }
     }

3、堆的应用-优先级队列
基本操作:一是返回最高优先级对象,一个是添加新的对象
操作-入队列(大堆):
1、首先按照尾插方式放入数组
2、比较其和双亲的值的大小,如果双亲的值大,则满足堆的性质,插入结束
3、否则,交换其和双亲位置的值,重新进行2、3步骤
4、直达根节点
代码:

public static void shiftup(int[] array,int index){
    while(index>0){
       int parent=(index-1)/2;
       if(array[parent]>=array[index]){
          break;
      }
       
       int t=array[parent];
       array[parent]=array[index];
       array[index]=t;
       
       index=parent;
       }
}
        操作-出队列,即:
        为了防止破坏堆的结构,删除时并不是直接将堆顶元素删除,而是用数组的最后一个元素替换堆顶元素,然后通过向下调整方式重新调整成堆。
        返回队首元素:返回堆顶元素即可
        代码:
public class MyPriorityQueue{
    private int[] array=new int[100];
    private int size=0;
    
    public void offer(int e){
       array[size++]=e;
       shiftDown(array,size,0);
       return oldValue;
     }
      
     public int peek(){
        return array[0];
      }
   }

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值