优先级队列

优先级队列

1.直接new一个PriorityQueue

PriorityQueue底层默认是一个小堆。

代码示例:

public class Test{
   public static void main (String[] args) {
      Queue<Integer> queue = new PriorityQueue<>();
      queue.offer(10);
      queue.offer(15);
      queue.offer(11);
}

插入完成后,该队列从队头至队尾:10、11、15

2.自己实现一个优先级队列

优先级队列的实现方式有很多,但最常见的是使用堆来构建。

这里以建大堆为例:

入队列

过程:

  1. 首先按尾插方式放入数组
  2. 比较其和其双亲的值的大小,如果双亲的值大,则满足堆的性质,插入结束
  3. 否则,交换其和双亲位置的值,重新进行 2、3 步骤
  4. 直到根结点
出队列(优先级最高的出队列)

为了防止破坏堆的结构,删除时并不是直接将堆顶元素删除,而是用数组的最后一个元素替换堆顶元素,然后通过向下调整方式重新调整成堆

返回队首元素

返回堆顶的元素,但不删除。

优先级队列代码示例:
public class TestHeap {
   public int[] elem;
   public int usedSize;
    
   public TestHeap() {
      this.elem = new int[20];
      this.usedSize = usedSize;
   }
//首先,建堆
   public void createHeap(int[] array) {
       for(int i = 0;i < array.length;i++){
           elem[i] = array[i];
           this.usedSize++;
       }
       //从最后一棵子树开始向下调整,
       for(int i = (this.usedSize - 1 -1 )/2;i >= 0;i--){
            adjustDown(i,this.usedSize);
       }
   }
//向下调整
   public void adjustDown(int root,int len) {
       int parent = root;
       int child = 2 * parent + 1;
       while(child < this.usedSize) {
           if(child + 1 < this.usedSize && elem[child] < elem[child + 1]) {
              child = child + 1;
           }
           if(elem[child] > elem[parent]) {
              int tmp = elem[child];
              elem[child] = elem[parent];
              elem[parent] = tmp;
              parent = child;
              child = 2 * parent + 1;
           } else {
               break;
           }
       }
   }
   
    public boolean isFull(){
        if(this.usedSize == elem.length){
            return true;
        }
        return false;
    }

    //入队:放到数组的最后一个下标,之后向上调整

    public void pushHeap(int val){
        if(isFull()){
            this.elem = Arrays.copyOf(this.elem,this.elem.length*2);
        }
        elem[usedSize] = val;
        this.usedSize++;
        adjustUp(this.usedSize-1);
    }
    //向上调整
    public void adjustUp(int child){
        int parent = (child-1)/2;
        while( child > 0){
            if(elem[child] > elem[parent]){
                int tmp = elem[child];
                elem[child] = elem[parent];
                elem[parent] = tmp;
                child = parent;
                parent = (child-1)/2;
            }else{
                break;
            }
        }
    }
    //出队,对头元素出队
    public void popHeap(){
        //0.如果堆为空
        //1.根顶元素和最后一个元素进行交换
        //2.向下调整,只需调整0号下标这棵树
        if(this.usedSize == 0){
            return;
        }
        int tmp = elem[0];
        elem[0] = elem[this.usedSize-1];
        this.usedSize--;
        adjustDown(0,this.usedSize);
    }

    //得到堆顶元素
    public int getPop(){
        if(this.usedSize == 0){
            return -1;
        }
        return this.elem[0];
    }

    public void display(){
        for(int i = 0;i < this.usedSize;i++){
            System.out.print(elem[i] + " ");
        }
        System.out.println();
    }
    
    //堆排序
    public void heapSort() {
        //end为每次调整的结束位置
        int end = this.usedSize-1;
        while(end > 0){
            int tmp = this.elem[0];
            this.elem[0] = this.elem[end];
            this.elem[end] = tmp;
            adjustDown(0,end);
            end--;
        }
    }
}
//  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值