集合框架中——自定义优先级队列priorityQueue(小根堆)

优先级队列:

优先级队列以数组形式存储数据,以树形形式组织元素的。
在以树形形式组织的时候,默认为小根堆形式。
小根堆:每一个父节点都小于它的左右节点。

在树中:

  • 已知子节点,求父节点的公式为:(n-1)/2
  • 已知父节点:
    ①求左孩子:2n+1
    ②求右孩子:2n+2

在这里插入图片描述

思路:

自定义一个类,属性为存放元素的数组和存放元素的下标,

  • 添加元素
    添加元素时,往树的最后一个添加,然后在从下往上将整个树重新调整成小根堆。
    向上调整:判断当前添加的值和父节点的大小,如果父节点大,交换值。然后继续以当前位置为孩子,判读当前位置和其父节点的大小,如果父节点大,交换,依次向上判断,直到判断到根节点。如果父节点小于当前孩子,则说明已经满足小根堆的要求,则直接结束。
  • 删除元素
    把最后一个元素放入根节点的位置,进行覆盖,然后将最后一个节点进行置空,有助于GC进行回收,最后从上向下重新调整成为小根堆。
    向下调整:从根节点开始,判断根节点和左右孩子的最小值的大小,如果根节点小,则满足小根堆,否则,交换根节点和左后孩子的最小值,依次向下判断。
代码:
class PriorityQueue {
    int[] array;  //存放元素的数组
    int size;//存放元素的下标

    public PriorityQueue() {
        this(10);
    }

    public PriorityQueue(int s) {
        this.array = new int[s];
        this.size = 0;
    }

    public boolean add(int val) {  //插入:往最后一个插入. 插入的和父节点比较,比父小,调整
        if (size == 0) {
            array[size++] = val;
        } else {
            array[size] = val;//先插入再调整为小根堆
            adjustUp(size, val);
        }
        return true;
    }
    private void adjustUp(int index,int value){  //从下往上调整
        while (index > 0) {
            int parent = (index - 1) >>> 1; //已知子求父
            if (this.array[parent] <= value) {  //父节点小于value,满足小根堆直接跳出
                break;
            }
            //父节点大于value
            this.array[index] = this.array[parent];
            index = parent; //更新Index的值,继续判断父节点
        }
        this.array[index] = value;
        size++;
    }
    public boolean remove(){
        if(size == 0) {
            System.out.println("无元素!");
            return false;
        }
        if(size == 1){
            size--;
            System.out.println("删除成功");
        }
        if(size>1) {
            array[0] = array[size - 1]; //将最后一个元素放入根节点(覆盖根节点)
            adjustDown(0); //从上向下调整为小根堆

        } return true;
    }
    private void adjustDown(int index) { //从上往下调,从根节点开始
        //已知根节点,判断根节点和左右子的大小
        int tmp = array[index];
        int leftChild = index * 2 + 1; // 左节点
        for (int i = leftChild; i <= size-1 ; i = 2*i+1) {  //进入for循环,说明有左孩子, i的步进是为了寻找下一个左右孩子,进行下一步左右孩子大小的判断
            //判断是否有孩子,如果有,找到左右的最小值
              if(i < size-1 && array[i] > array[i+1]){  //右孩子小,更新i的值
                  i++;
              }
              if(array[i] < tmp) {  //小的数赋给根节点
                  array[index] = array[i];
                  index = i;
              }else {
                  break;
              }
        }
        array[index] = tmp;
        size--;
    }
    public void show(){
        for (int i = 0; i < size ; i++) {
            System.out.print(array[i]+" ");
        }
        System.out.println();
    }
}


public class QueueSmallDemo305  {


    public static void main(String[] args) {
        PriorityQueue priorityQueue = new PriorityQueue();
        priorityQueue.add(1);
        priorityQueue.add(3);
        priorityQueue.add(6);
        priorityQueue.add(2);
        priorityQueue.add(8);
        priorityQueue.add(4);

       priorityQueue.show();   //1  2  4  3  8  6

       priorityQueue.remove();
       priorityQueue.remove();

       priorityQueue.show();
    }
}

实现结果:

在这里插入图片描述
它的小根堆树形表示出来为:
在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值