优先级队列(堆)

1.为什么使用堆?

        用数组保存二叉树,用层序遍历方式放在数组中。但只适合完全二叉树,因为非完全二叉树会有空间的浪费。

所以这种方式主要用法就是堆的表示

2.什么叫优先级对列

队列是现金先出的数据结构,但有时候操作的数据是带有优先级的,所以使用优先级队列。

3.优先级队列的两个基本操作

<1>.返回最高优先级对象.

<2>,添加新对象

4.优先级队列

//使用时必须导入PriorityQueue所在的包
/*
1.元素必须能比较大小
2.插入和删除元素的时间复杂度为O(log2N)
3.底层使用堆
*/
import java.util.PriorityQueue;
    public static void main(String[] args) {
        //定义整型的优先级队列:默认头部的元素为最小的元素
        PriorityQueue<Integer> priorityQueue=new PriorityQueue<>();
        //插入元素
        priorityQueue.offer(13);
        priorityQueue.offer(3);
        priorityQueue.offer(8);
        priorityQueue.offer(49);
        //获取队列的头部————> 3
        System.out.println(priorityQueue.peek());
        //删除队列的头部————> 3
        System.out.println(priorityQueue.poll());
        //获取队列的头部————> 8
        System.out.println(priorityQueue.peek());

    }
}

5.模拟实现优先级队列——>堆

大堆:父亲结点比孩子结点都大

小堆:父亲结点比孩子结点都小

6.堆的作用

快速找集合中的最值

testHeap中的代码

package priorityqueue;

import java.util.Arrays;

public class TestHeap {
    //堆的底层是一个数组
    public int[] elem;
    public int usedSize;
    public TestHeap(){
        this.elem=new int[10];
    }
    //像下调整
    public void adjustDown(int parent,int len){
        //左孩子
        int child=2*parent+1;
        //首先判断是否有左孩子
        while(child<len){
                //1.首先判断是否有右孩子,如果有,child保存左右孩子最大值下标
                //左孩子和右孩子比较大小,但是child+1不能越界,
                if(child+1<len && elem[child]<elem[child+1]) {
                    child++;
                }
                //child当中存储的就是最大值下标
                //如果大孩子的值和双亲比较还大的话就交换
                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 void initHeap(int[] array){
        //将array数组的元素放在elem数组中
        for (int i = 0; i < array.length; i++) {
            this.elem[i]=array[i];
            usedSize++;

        }

        //已知孩子结点求父亲结点则————>双亲的下标=(孩子下标—1)/2
        for (int i = (usedSize-1-1)/2; i >=0; i--) {
            adjustDown(i,usedSize);

        }
        System.out.println("===============");

    }


    //向上调整
    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 push(int val){
        //如果满了放不下,先扩充数组
        if(isFull()){
            elem= Arrays.copyOf(elem,2*elem.length);
        }
        elem[usedSize]=val;
        usedSize++;
        //将新加的结点传进去
        adjustUp(usedSize-1);
        System.out.println("========");



    }

    //堆的删除:只能删除堆顶元素
    /*
    1.让堆顶元素和最后一个元素交换
     */
    public void pop(){
        //1.判空
        if(isEmpty()) return;
        //2.交换栈顶和最后一个元素
        int tmp=elem[0];
        elem[0]=elem[usedSize-1];
        elem[usedSize-1]=tmp;
        //删除最后一个元素
        usedSize--;
        //调整
        adjustDown(0,usedSize);

    }
    public boolean isEmpty(){
        return usedSize==0;
    }
    //当前数组的长度和使用长度一样,说明数组已经满了
    public boolean isFull(){
        return usedSize==elem.length;
    }

    //堆排序
    public void heapSort(){
        int end=usedSize-1;
        while(end>0){
            int tmp=elem[0];
            elem[0]=elem[end];
            elem[end]=tmp;
            adjustDown(0,end);
            end--;

        }

    }
    public void show(){
        for (int i = 0; i < usedSize; i++) {
            System.out.print(elem[i]+" ");
            
        }
        System.out.println();
    }


}
TestPriorityQueue的代码
​
import java.util.PriorityQueue;
public class TestPriorityQueue {
    public static void main(String[] args) {
        int[] array = {27, 15, 19, 18, 28, 34, 65, 49, 25, 37};
        TestHeap testHeap = new TestHeap();
        testHeap.initHeap(array);
        System.out.println("================");
        //testHeap.push(80);
        testHeap.pop();
        testHeap.heapSort();
        testHeap.show();
    }

}

​

7.堆的应用

例如求前K个最小的——>

大堆:每次弹出来的都是大元素,剩下的就是小的

例如求前K个最大的——>

小堆:每次弹出来的都是小元素,剩下的就是大的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值