算法练习day6——190323(求中位数、堆排序、稳定性)
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~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.堆排序 2.希尔排序 3.快速排序 4.选择排序 口诀:一堆(堆)希尔(希尔)快(快速)选(选择) 二.常见排序算法稳定性分析 1.堆排序稳定性分析 我们知道堆的结构是节 ...
- Leetcode算法题:两个有序数组求中位数
Leetcode算法题:两个有序数组求中位数 要求时间复杂度为O(log(m+n)) 思路: 暴力解决:合并数组并排序,简单且一定能实现,时间复杂度O(m+n) 由于两个数组已经排好序,可一边排序一边 ...
- O(n)的时间复杂度求中位数
O(n)的时间复杂度求中位数 O(n)中位数问题是指:在O(n)的时间复杂度内找到一个无序序列的中位数. 在开始O(n)时间复杂度求中位数之前,先手写一下快速排序. 快速排序的实现 Reference ...
- java中求中位数_java 计算中位数的实现方法
最近工作需要 要求把python的代码写成java版本,python中有一个np.median()求中位数的方法,java决定手写一个 先说说什么是中位数: 中位数就是中间的那个数, 如果一个集合是奇 ...
- 堆实战(动态数据流求top k大元素,动态数据流求中位数)
动态数据集合中求top k大元素 第1大,第2大 ...第k大 k是这群体里最小的所以要建立个小顶堆 只需要维护一个大小为k的小顶堆 即可当来的元素(newCome)> 堆顶元素(smallTo ...
- 求中位数_图解面试题:如何分析中位数?
学校每次考试完,都会有一个成绩表.例如,表中第1行表示编号为1的用户选择了C++岗位,该科目考了11001分. 问题:写一个sql语句查询每个岗位的中位数位置的范围,并且按岗位升序排序,结果如下: 解 ...
- 算法训练 6-1 递归求二项式系数值
算法训练 6-1 递归求二项式系数值 问题描述 样例输入 一个满足题目要求的输入范例. 3 10 样例输出 与上面的样例输入对应的输出. 数据规模和约定 输入数据中每一个数的范围. 例:结果在in ...
- 给定一个整数序列,求中位数
问题描述: 给定一个整数序列,求中位数.如果序列个数为奇数,中位数为升序的中间位置,如果是偶数,这位升序的中间两个数的平均值. 输入: 输入包含多组测试数据,每一组第一行为n(n<104)表示这 ...
- Python实现相空间重构求关联维数——GP算法、自相关法求时间延迟tau、最近邻算法求嵌入维数m
Python实现相空间重构求关联维数--GP算法.自相关法求时间延迟tau.最近邻算法求嵌入维数m GP算法: 若有一维时间序列为{x1,x2,-,xn},对其进行相空间重构得到高维相空间的一系列向量 ...
最新文章
- 有关任意多条曲线的拟合度算法
- hdu1671 字典树记录前缀出现次数
- Servlet 单例多线程
- mysql数据库引擎博客_mysql 数据库引擎常识全集
- MyBatis框架——mybatis插入数据返回主键(mysql、oracle)
- jsp页面调用ajax,在jsp中使用jquery的ajax
- 05.序列模型 W1.循环序列模型(作业:手写RNN+恐龙名字生成)
- 程序员夏天格子衫,冬天穿什么?
- e0266 cout 不明确_荐书 | 不正义的时代,识别不正义的多重面孔
- 问题2:无法打开包括文件:“windows.h”:No such file or directory
- 4种Dolby声场技术的区别
- 使用docker搭建couchbase集群
- 绝对估值法和相对估值法
- 关于Cat,同轴,光纤等以太网电缆的所有信息
- [翻译]Reactor Netty参考指南 - 8.UDP客户端
- Chrome安装插件Save All Resources
- linux基础-- 桌面系统如何切换命令窗口
- 5G DL PRS(Positioning Reference Signal) -- 下行定位参考信号
- 如何评价1700亿参数的GPT-3?
- 我为什么不建议使用OpenDNS和Google Public DNS