1.求中位数

有一个流,不断输出数,然后会不停地询问已输出的那些书的中位数。

解决方法:用一个大根堆,一个小根堆存那些已输出的数。

  • 大根堆中存储较小的N/2个数;
  • 小根堆中存储较大的N/2个数;
  • 这样,中位数=(大根堆的根+小根堆的根)/2;
    • 大根堆的根是较小的N/2中最大的;
    • 小根堆的根是较大的N/2中最小的;
    • 两者刚卡在数据的中间。

具体步骤:

  • 输出的第一个数先放在大根堆;
  • 后面输出的数小于等于大根堆的根,则如大根堆,然后调整堆;
  • 若大于大根堆中的根,则入小根堆,调整堆;
  • 若大根堆中的节点数比小根堆中的节点数多2个,则将大根堆的根取出,如小根堆;反之亦然。
    • 用heapsize记录已形成的堆的大小;
    • 取根的结果:
      • 大根堆中最大的进入小根堆,满足小根堆中的数都大于大根堆中的数;
      • 小根堆中最小的进入大根堆,满足小根堆中的数都大于大根堆中的数。

如何弹出大顶堆的根(小根堆类似):

  • 最后一个元素和堆顶元素交换;
  • 堆范围-1;
  • 再调整堆。

比如:

1、交换6和1:

2、堆范围-1(0~4变为0~3):

3、调整堆:

调整之后:

2.堆的重要性

几乎一切的贪心结构都是用堆完成的。

优先级队列就是堆!

3.堆排序

步骤:

  1. 建立大根堆(并不是有序的);
  2. 将堆顶位置的数和最后一个数交换位置;
  3. 堆范围-1;
  4. 调整堆;
  5. 重复2~4,直至堆大小减为0。

代码实现:

package Sort;public class HeapSort {public static void main(String[] args) {int[] array= {2,1,3,6,0,4};for(int i=0;i<array.length;i++)System.out.print(array[i]+"  ");System.out.println();heapsort(array);for(int i=0;i<array.length;i++)System.out.print(array[i]+"  ");}public static void heapsort(int[] arr) {if(arr==null||arr.length<2)return;for(int i=0;i<arr.length;i++) {heapInsert(arr,i);}int heapsize=arr.length;swap(arr,0,--heapsize);while(heapsize>0) {heapify(arr,0,heapsize);swap(arr,0,--heapsize);}}public static void heapInsert(int[] arr,int i) {while(arr[i]>arr[(i-1)/2]) {swap(arr,i,(i-1)/2);i=(i-1)/2;//变为自己的父节点,继续向上比较}}public static void heapify(int[] arr,int i,int heapsize) {int left=i*2+1;while(left<heapsize) {if(left+1<heapsize) {int largest=max(arr,i,left,left+1);if(largest==arr[i])//它已经是最大的了break;else if(largest==arr[left]) {swap(arr,i,left);i=left;}else {swap(arr,i,left+1);i=left+1;}left=2*i+1;}else {if(arr[i]<arr[left]) {swap(arr,i,left);i=left;left=i*2+1;}elsebreak;}}}public static void swap(int[] arr,int i,int j) {int temp=arr[i];arr[i]=arr[j];arr[j]=temp;}public static int max(int[] arr,int i,int j,int k) {int num=arr[i]>arr[j]?arr[i]:arr[j];return num>arr[k]?num:arr[k];}
}

运行结果:

4.排序算法的稳定性

4.1 3个常规的的排序

4.1.1 冒泡排序

可以做到稳定

相等时不交换,让后面的数继续往后比较即可。

第一次比较之后,交换:

第二次比较之后,交换:

第三次比较之后,相等,不交换:

让后面的7再和之后的数进行比较,则可保证这两个7的相对位置不变。

4.1.2 插入排序

可是实现为稳定的。

和前面数相等时,不交换。

第一次比较之后,交换:

第二次比较,相等,不交换,停止:

此时两个6的相对位置没变。

4.1.3 选择排序

无法做到稳定性。

第一次比较之后,0个第一个5进行交换:

现在第一个5和其他5的相对位置发生了变化,它从第一个变为了第四个。——不稳定。

4.2 d的三个排序

4.2.1 归并排序

可以做到稳定

merge时,若左=右,则先拷贝左,保证右和左相同的值不会跨到左的前面。

p1和p2指向的两个位置的值相等,都为3,先把p1指向的3拷贝到辅助数组;

p1右移;

此时p1指向的还为3,则继续将它拷贝到辅助数组;

p1右移;

p1的值4>3,将p2指向的3拷贝到辅助数组。

这种方式即可保证三个3的相对位置不变。

4.2.2 快速排序

不能保证稳定性。

因为partation过程无法实现稳定性。

荷兰国旗问题同理。

若目前情况如下所示:

此时,要处理的元素是3,它小于4,将它与最前面的4进行交换:

第一个4就变成了第三个4,不稳定。

题:奇数放在数组左边, 偶数放在数组右边, 还要求原始的相对次序不变。

此题类似于快排的Partation过程。

若要实现,<01 stable sort>有方法可解决,但特变难。

4.2.3 堆排序

无法实现稳定性。

因为交换过程中不关心相等值。

原始堆如下:

此时插入一个5:

需要对堆进行调整:

首先就是把5和它的父节点的4进行交换;

目前,4的相对位置已发生变化,所以堆排序不是稳定的。

4.3

排序算法 是否稳定
冒泡
插入
选择 ×
归并
快排 ×
堆排 ×

表格总结

4.4 稳定性的意义

可以利用前面比较的结果。

比如实际应用中,要对学生的一系列属性进行排序,具体信息如下:

首先按成绩从高到低进行排序:

再按班级进行排序:

则按班级排好之后,班级内的成绩也是按从高到低次序排列的,利用了前面按成绩排序的结果。

  • 班级号相同的,按原始的相对位置(成绩从高到低的次序)调到了一块。

5. 工程中的综合排序算法

5.1 数组很大

先对数组内的元素类型进行判断:

5.1.1 元素类型为基本类型

则相同值之间无差异,不用氛原始顺序,所以可以采用不稳定的排序算法。

使用快速排序

5.1.2 元素类型为自定义数据类型

例如:学生,需要先按成绩排序,再按班级号排序。即成绩相同的个体之间也是有差异的。

需要保证此次排序之前相等值的原始顺序。需要使用稳定的排序算法。

使用归并排序

5.2 若数组比较短,<60

使用插入排序

虽然它是,但是常数项极低,在元素个数小的情况下,非常有效。

算法练习day6——190323(求中位数、堆排序、稳定性)相关推荐

  1. 堆排序稳定性举例_常见排序算法的稳定性分析

    一.不稳定排序算法有哪些 1.堆排序 2.希尔排序 3.快速排序 4.选择排序 口诀:一堆(堆)希尔(希尔)快(快速)选(选择) 二.常见排序算法稳定性分析 1.堆排序稳定性分析 我们知道堆的结构是节 ...

  2. Leetcode算法题:两个有序数组求中位数

    Leetcode算法题:两个有序数组求中位数 要求时间复杂度为O(log(m+n)) 思路: 暴力解决:合并数组并排序,简单且一定能实现,时间复杂度O(m+n) 由于两个数组已经排好序,可一边排序一边 ...

  3. O(n)的时间复杂度求中位数

    O(n)的时间复杂度求中位数 O(n)中位数问题是指:在O(n)的时间复杂度内找到一个无序序列的中位数. 在开始O(n)时间复杂度求中位数之前,先手写一下快速排序. 快速排序的实现 Reference ...

  4. java中求中位数_java 计算中位数的实现方法

    最近工作需要 要求把python的代码写成java版本,python中有一个np.median()求中位数的方法,java决定手写一个 先说说什么是中位数: 中位数就是中间的那个数, 如果一个集合是奇 ...

  5. 堆实战(动态数据流求top k大元素,动态数据流求中位数)

    动态数据集合中求top k大元素 第1大,第2大 ...第k大 k是这群体里最小的所以要建立个小顶堆 只需要维护一个大小为k的小顶堆 即可当来的元素(newCome)> 堆顶元素(smallTo ...

  6. 求中位数_图解面试题:如何分析中位数?

    学校每次考试完,都会有一个成绩表.例如,表中第1行表示编号为1的用户选择了C++岗位,该科目考了11001分. 问题:写一个sql语句查询每个岗位的中位数位置的范围,并且按岗位升序排序,结果如下: 解 ...

  7. 算法训练 6-1 递归求二项式系数值

    算法训练 6-1 递归求二项式系数值   问题描述 样例输入 一个满足题目要求的输入范例. 3 10 样例输出 与上面的样例输入对应的输出. 数据规模和约定 输入数据中每一个数的范围. 例:结果在in ...

  8. 给定一个整数序列,求中位数

    问题描述: 给定一个整数序列,求中位数.如果序列个数为奇数,中位数为升序的中间位置,如果是偶数,这位升序的中间两个数的平均值. 输入: 输入包含多组测试数据,每一组第一行为n(n<104)表示这 ...

  9. Python实现相空间重构求关联维数——GP算法、自相关法求时间延迟tau、最近邻算法求嵌入维数m

    Python实现相空间重构求关联维数--GP算法.自相关法求时间延迟tau.最近邻算法求嵌入维数m GP算法: 若有一维时间序列为{x1,x2,-,xn},对其进行相空间重构得到高维相空间的一系列向量 ...

最新文章

  1. 有关任意多条曲线的拟合度算法
  2. hdu1671 字典树记录前缀出现次数
  3. Servlet 单例多线程
  4. mysql数据库引擎博客_mysql 数据库引擎常识全集
  5. MyBatis框架——mybatis插入数据返回主键(mysql、oracle)
  6. jsp页面调用ajax,在jsp中使用jquery的ajax
  7. 05.序列模型 W1.循环序列模型(作业:手写RNN+恐龙名字生成)
  8. 程序员夏天格子衫,冬天穿什么?
  9. e0266 cout 不明确_荐书 | 不正义的时代,识别不正义的多重面孔
  10. 问题2:无法打开包括文件:“windows.h”:No such file or directory
  11. 4种Dolby声场技术的区别
  12. 使用docker搭建couchbase集群
  13. 绝对估值法和相对估值法
  14. 关于Cat,同轴,光纤等以太网电缆的所有信息
  15. [翻译]Reactor Netty参考指南 - 8.UDP客户端
  16. Chrome安装插件Save All Resources
  17. linux基础-- 桌面系统如何切换命令窗口
  18. 5G DL PRS(Positioning Reference Signal) -- 下行定位参考信号
  19. 如何评价1700亿参数的GPT-3?
  20. 我为什么不建议使用OpenDNS和Google Public DNS

热门文章

  1. 【单机实现系列】SCDPM2012实现数据保护
  2. matplotlib 一张图多个图,如何在Matplotlib中绘制同一个图上的多个函数?
  3. GitHub 2W 星:一键生成前后端代码
  4. LNMP 环境遇到的权限问题
  5. 看完这份MySQL 性能调优文档,我把面试问我数据库调优的面试官虐哭了
  6. springboot整合视图层Thymeleaf、freemarker
  7. linux deepin/ubuntu安装flameshot火焰截图
  8. kafka在zk中的目录
  9. k8s集群DNS无法解析问题的处理过程
  10. k8s节点亲和性:pod和node的亲和性、硬策略、软策略