优先级队列(堆)

1.什么是堆

堆是一种特殊的数据结构,通常是一个可以被看做一棵树的数组对象。它使用数组保存二叉树结构,即将二叉树用层序遍历结果放入数组中。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆

2.堆满足的性质

  • 堆中某个节点的值总是不大于或不小于其父节点的值;
  • 堆总是一棵完全二叉树。

2.1 已知双亲结点(parent)下标

左节点(leftIndex)=parent2+1 ;
右节点(rightIndex)=parent
2+2;

2.2 已知子结点(不区分左右)(child)下标

父节点(parentIndex)=(child-1)/2;

3.堆的一些操作

3.1 向下调整

前提:左右子树已经满足堆的性质
实现:

//小堆
public static void smallHeapAdjustDown(long[]array,int size,int index){
        while(index*2+1<size){//叶子结点存在
            int minIndex=index*2+1;//现将最小值的下标定为左节点的下标
            int rightIndex=minIndex+1;
            if(rightIndex<size&&array[rightIndex]<array[minIndex]){
            //右结点存在并且右结点的值小于左节点的值时将最小值的下标变为右结点
                minIndex=rightIndex;
            }
            //当父节点的值已经小于等于最小的子节点的值时结束向下调整
            if(array[index]<=array[minIndex]){
                break;
            }
            swap(array,index,minIndex);//交换父节点和最小子节点的值
            index=minIndex;//将index变为minIndex继续循环
        }
    }
    private static void swap(int[] array, int index, int minIndex) {
        int t=array[index];
        array[index]=array[minIndex];
        array[minIndex]=t;
    }

测试:
在这里插入图片描述

3.2 建堆

给出一个数组,这个数组逻辑上可以看做一颗完全二叉树,但是还不是一个堆,现在我们通过算法,把它构建成一个堆。根节点左右子树不是堆,我们怎么调整呢?这里我们从倒数的第一个非叶子节点的子树开始调整,一直
调整到根节点的树,就可以调整成堆。

  • 实现
    public static void createHeap(int []array){
        int index=array.length-1;
        index=(index-1)/2;
        for(int i=index;i>=0;i--){
            bigHeapAdjustDown(array,array.length,i);
        }
    }
    private static void bigHeapAdjustDown(int[]array,int size,int index){
        while(index*2+1<size){
            int maxIndex=index*2+1;
            if(maxIndex+1<size&&array[maxIndex+1]>array[maxIndex]){
                maxIndex++;
            }
            if(array[index]>=array[maxIndex]){
                break;
            }
            swap(array,index,maxIndex);
            index=maxIndex;
        }
    }
    private static void swap(int[] array, int index, int minIndex) {
        int t=array[index];
        array[index]=array[minIndex];
        array[minIndex]=t;
    }

测试:
在这里插入图片描述

3.3优先级队列的实现

public class MyPriorityQueue {
    private int []array;
    private int size;
    MyPriorityQueue(){
        this.array=new int[100];
        size=0;
    }
    public boolean add(int val){
        if(size>=array.length){
            return false;
        }
        array[size++]=val;
        adjustUp(size-1);
        return true;
    }
    private  void swap(int[] array, int index, int minIndex) {
        int t=array[index];
        array[index]=array[minIndex];
        array[minIndex]=t;
    }
    private void adjustUp(int index) {
        while(index>0){
            int parentIndex=(index-1)/2;
            if(array[parentIndex]>array[index]){
                break;
            }
            swap(array,parentIndex,index);
            index=parentIndex;
        }
    }
    public int poll() {
        if (size == 0) {
            return -1;
        }
        int val = this.array[0];
        array[0] = array[size-1];
        size--;
        bigHeapAdjustDown(0);
        return val;
    }
    public void bigHeapAdjustDown(int index){
        while(index*2+1<size){
            int maxIndex=index*2+1;
            if(maxIndex+1<size&&array[maxIndex+1]>array[maxIndex]){
                maxIndex++;
            }
            if(array[index]>=array[maxIndex]){
                break;
            }
            swap(array,index,maxIndex);
            index=maxIndex;
        }
    }
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值