前言

为什么要是用优先队?优先队列又是什么?

许多应用程序都系要处理有序的元素,但不应定要求它们完全有序,或者不一定要一次就将它们排序。很多时候我们回收集一些元素,然后处处理当前键值最大的元素,然后再收集更多的元素,再狐狸当前键值最大的元素……举个生活中的例子吧,就像我们用的手机一样,手机里面有很多进程,但是有一个进程的优先级特别高,那就是来电显示(不然的话,放你在打游戏的时候也不会因为来电而退出,嘿嘿)。优先队列是局部有序的,它并不将所有的元素都排成成有序的。

基本函数

  1. Key delmax()用来删除队列中最大的元素
  2. void insert(Key value)用来插入新元素
  3. boolean isEmpty() 用来判断队列是否为空
  4. int getSize() 返回 队列中的元素个数
  5. Key getMax() 返回队列中的最大值元素

我们用二叉堆表示法来实现优先队列,首先来介绍一下什么是二叉堆

在一个二叉树里面,如果每个结点都大于等于它的两个子结点的时候,那么那它就是堆有序的;二叉堆是一组能够用堆有序的完全二叉树(若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。)排序的元素,并在数组中按照层级存储(为了表示方便,我们不使用数组中的第一个元素)。所以根节点的地方是队列中键值最大的元素。

函数具体实现(采用java语言)

堆实现的比较和交换算法

private boolean less(int i,int j) {return pq[i] <pq[j];}private void exch(int i,int j) {int temp = pq[i];pq[i]=pq[j];pq[j]=temp;}

由下至上的堆有序化—Swim(上浮)

private void swim(int k) { // 上浮   元素最大比较次数为logN+1次 (也就是二叉树为满二叉树的时候,再往里面插入元素的时候)while(k>1&&less(k/2,k)) {exch(k/2,k);k=k/2;}}

由上至下的堆有序化—Sink(下沉)

private void sink(int k) {
//下沉 一共循环logN次 元素比较次数为2*logN次while(2*k<=N) {int j=2*k;if(j<N && less(j,j+1)) {j++;}if(!less(k,j)) {break;}exch(k,j);k=j;}}

插入函数和删除最大元素最大函数

public void insert(int elem) {pq[++N]=elem;swim(N);}public int delMax() {int max=pq[1];exch(1, N--);//交换根节点和最后一个节点,并删除交换后的最后一     个节点 也就是之前的根节点//pq[N+1] = (Integer) null ;//防止对象游离  基本类型元素不可用sink(1);;//恢复堆得有序性return max;}

基于堆的优先队全部代码

package 优先队列1;public class PriorityQueue {//堆顶元素最大private int[] pq;private int N = 0; //存储于pq[1...N]中,pq[0]没有使用private boolean less(int i,int j) {return pq[i] <pq[j];}private void exch(int i,int j) {int temp = pq[i];pq[i]=pq[j];pq[j]=temp;}public PriorityQueue(int length) {this.pq=new int[length+1];  //下标为0的元素不用  元素从下标为1的地方开始}private void swim(int k) { // 上浮   元素最大比较次数为logN+1次 (也就是二叉树为满二叉树的时候,再往里面插入元素的时候)while(k>1&&less(k/2,k)) {exch(k/2,k);k=k/2;}}private void sink(int k) { //下沉   一共循环logN次   元素比较次数为2*logN次while(2*k<=N) {int j=2*k;if(j<N && less(j,j+1)) {j++;}if(!less(k,j)) {break;}exch(k,j);k=j;}}public int getElemSize(){return N;}public boolean isEmpty() {return N == 0;}public void insert(int elem) {pq[++N]=elem;swim(N);}public int delMax() {int max=pq[1];exch(1, N--);//交换根节点和最后一个节点,并删除交换后的最后一个节点 也就是之前的根节点//pq[N+1] = (Integer) null ;//防止对象游离  基本类型元素不可用sink(1);;//恢复堆得有序性return max;}private void display() {for(int i=1;i<=N;++i)System.out.print(pq[i] + " ");System.out.println();}public static void main(String[] args) {// TODO Auto-generated method stubPriorityQueue PQ = new PriorityQueue(12);PQ.insert(12);PQ.insert(15);PQ.insert(2);PQ.insert(18);PQ.insert(7);PQ.insert(7);System.out.println("The count of elem is "+PQ.getElemSize());System.out.print("All elem are :");PQ.display();System.out.println("Now,the max elem in priorityQueue is "+PQ.delMax());System.out.println("Now,the max elem in priorityQueue is "+PQ.delMax());System.out.println("Now,the max elem in priorityQueue is "+PQ.delMax());}
}

运行结果如下:

算法分析

  • sink()方法中,一共循环logN次 元素最大比较次数为2*logN次
  • swim()方法中, 元素最大比较次数为logN+1次,也就是二叉树为满二叉树的时候,再往里面插入元素的时候。
  • 算法的分析 用图表表示为:

    其中,
  • 第一行unordered array是没有排序的数组,插入和删除还有求最大元素的算法复杂度分别为1,n,n。
  • 第二行ordered array是排好序的数组,插入和删除还有求最大元素的算法复杂度分别为n,1,1。
  • 第三行binary heap是二叉堆,插入和删除还有求最大元素的算法复杂度分别为log n,2*log n,1。
  • 第四行d-ary heap是d叉堆(也就是每个结点有d个子结点),插入和删除还有求最大元素的算法复杂度分别为logd n,d*logd n,1
  • sweet spot: d = 4 意思就是说最好的情况是当d=4的时候,算法效率比较好。

改进版的堆排序请参考

算法–优先队列之堆排序((二)升级版)

优先队列之堆排序(一)相关推荐

  1. 优先队列之堆排序((二)升级版)

    续 优先队列之堆排序(一) 上节在优先队列之堆排序(一)中介绍了优先队列的基本概念和实现算法,在本节中,我将为大家介绍一下关于对上节算法的改进一节该改进之后的算法复杂度. 在上节的delMAx()方法 ...

  2. MYSQL实现ORDER BY LIMIT的方法以及优先队列(堆排序)

    一.MYSQL中的LIMIT和ORACLE中的分页 在MYSQL官方文档中描述limit是在结果集中返回你需要的数据,它可以尽快的返回需要的行而不用管剩下的行, 在ORACLE中也有相关的语法比如 1 ...

  3. 硬核!手写一个优先队列

    文章收录在首发公众号:bigsai 期待你的到访! 前言 事情还要从一个故事讲起: 对于上面那只可爱的小狗狗不会,本篇即为该教程,首先,我要告诉这只可爱的小狗狗,这种问题你要使用的数据结构为优先队列, ...

  4. 排序(堆排序,快速排序,归并排序)

    前言:如果内容不全,说明还没复习到,复习时会陆续更新. 三种排序比较 堆排序,快速排序,归并排序平均复杂度都是O(nlogn).其中归并排序时间最稳定(最好最差的时间复杂度差距不大).快速排序平均时间 ...

  5. 2020-09-18

    算法与数据结构 课程安排 步骤1 算法与数据结构基础线性查找法试看排序基础数据结构基础:动态数组,栈和队列动态数据结构基础:链表步骤2 递归无处不在归并排序法快速排序法二分查找法二分搜索树步骤3 算法 ...

  6. 数据结构:堆(Heap)

    堆就是用数组实现的二叉树,所有它没有使用父指针或者子指针.堆根据"堆属性"来排序,"堆属性"决定了树中节点的位置. 堆的常用方法: 构建优先队列 支持堆排序 快 ...

  7. 剑指offer(60-67题)详解

    文章目录 60 把二叉树打印成多行 61 序列化二叉树 62 二叉搜索树第K个节点 63 数据流中的中位数 64 滑动窗口的最大值 65 矩阵中的路径 66 机器人的运动范围 67 剪绳子 欢迎关注个 ...

  8. 2017-2018-20172309 《程序设计与数据结构》第八周学习总结

    2017-2018-20172309 <程序设计与数据结构>第八周学习总结 一.教材学习内容总结 相信其它很多同学都是以小顶堆来介绍这一章内容,所以我将以大顶堆来介绍这章内容. 1.1 堆 ...

  9. vector删除第i个元素_LeetCode每日一题 Q215数组中的第K个最大元素

    Question 215: Kth Largest Element in an Array Difficulty: Medium 题目描述 在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的 ...

最新文章

  1. 分享一张SQLSERVER执行流程的图片
  2. 30秒内便能学会的30个超实用Python代码片段
  3. 21天实战人工智能系列:人工智能产品经理最佳实践(1)
  4. python 计算数字 k 在 0 到 n 中的出现的次数,k 可能是 0~9 的一个值
  5. Start vm by command line
  6. Django开发中问题和报错集合
  7. MooTools教程(4):函数和MooTools
  8. php验证邮箱的通用函数,PHP函数:PHP的通用检测函数总结
  9. Java——零基础速成学习
  10. 华为手机隐藏app图标_华为手机隐藏图标的设置方法
  11. 软件工程专业英语翻译【考研复试】
  12. 什么是对比度、亮度?教你在线调整图片色彩
  13. ubuntu下好用的录屏软件之Vokoscreen
  14. jQuery菜鸟教程01
  15. 超实用硬盘数据恢复工具介绍!永久免费
  16. 软件测试笔记_09_自动化相关概念【重要】
  17. c语言程序如何在keil中运行,keil c51中C程序的启动过程
  18. Matlab中IFFT/FFT注意事项及在OFDM仿真中的应用问题
  19. 腾讯会议攻转守,小鱼易连守转攻
  20. java lcs_LCS最长公共子序列java实现

热门文章

  1. 企业如何有效防止内部文件泄密风险...
  2. 超码、候选码、主码(主键)、主属性、非主属性、关系数据库中的依赖、关系数据库范式、反范式
  3. ampak正基RF定频安装指导
  4. [算法][面试题]疯狂队列-排列使得序列两两间“差值的绝对值“之和最大
  5. 二维码制作方法有什么?看完这篇你就会了
  6. 通过js动态为标签元素添加点击事件
  7. audioread-支持多种解码 (GStreamer + Core Audio + MAD + FFmpeg) 的python音频解码库
  8. 牛客练习赛51 C 勾股定理 (结论题)
  9. 2021云栖大会丨果断收藏!「混合云参会指南」来啦
  10. 计算机软件技术实习02