java数据结构--优先级队列(堆)

目录

概念:

堆:

堆的性质:

堆的存储方式:

堆的创建:

文字描述:

图解:

代码: 

堆的插入与删除: 

堆的插入:

堆的删除:


概念:

前面介绍过队列,队列是一种先进先出(FIFO)的数据结构,但有些情况下,操作的数据可能带有优先级,一般出队列时,可能需要优先级高的元素先出队列。在这种情况下,数据结构就提供了两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(PriorityQueue)。

堆:

堆实际就是在完全二叉树的基础上进行了一些元素的调整。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

堆的性质:

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

堆的存储方式:

从堆的概念可知,堆是一棵完全二叉树,存储的时候,是以数组的形式进行存储的,数组当中的数据,都是以层序遍历的方式存储的。

堆的创建:

首先我们要知道:已知孩子结点下标 i,父亲结点的下标为:(i-1)/2;已知父亲结点下标i,左孩子的下标为:2*i + 1 ,右孩子的下标为 2*i + 2 。

以小堆为例(向下调整)

文字描述:

1. 让parent标记需要调整的节点,child标记parent的左孩子(注意:parent如果有孩子一定先是有左孩子)

2. 如果parent的左孩子存在,即:child < size,进行以下操作,直到parent的左孩子不存在

3. 看parent右孩子是否存在,存在找到左右孩子中最小的孩子

4. 让child进行标注将parent与较小的孩子child比较,如果:parent小于较小的孩子child,调整结束否则:交换parent与较小的孩子child

5. 交换完成之后,parent中大的元素向下移动,可能导致子树不满足堆的性质,因此需要继续向下调整,即parent = child;child = parent*2+1; 然后继续从2开始执行。

图解:

 以27为根的左右子树都满足小堆的性质,只有根结点不满足,因此只用调整根结点的位置,就能得到一个小堆

代码: 

publicvoidshiftDown(int[]array,intparent){
//child先标记parent的左孩子,因为parent可能右左没有右                                                                    
    int child=2*parent+1;
    int size=array.length;
    while(child<size){
//如果右孩子存在,找到左右孩子中较小的孩子,用child进行标记
        if(child+1<size&&array[child+1]<array[child]){
            child+=1;
        }
//如果双亲比其最小的孩子还小,说明该结构已经满足堆的特性了
        if(array[parent]<=array[child]){
            break;
        }else{
//将双亲与较小的孩子交换
            int=array[parent];
            array[parent]=array[child];
            array[child]=t;
//parent中大的元素往下移动,可能会造成子树不满足堆的性质,因此需要继续向下调整                    
            parent=child;child=parent*2+1;
         }
    }
}

堆的插入与删除: 

堆的插入:

堆的插入总共需要两个步骤:

1. 先将元素放入到底层空间中(注意:空间不够时需要扩容)

2. 将最后新插入的节点向上调整,直到满足堆的性质

堆的删除:

1. 将堆顶元素对堆中最后一个元素交换

2. 将堆中有效数据个数减少一个

3. 对堆顶元素进行向下调整

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值