【优先队列:支持动态插入,寻找中位数】:poj3784,Running Median
2016-01-07 15:26
357 查看
维护一个最大堆和一个最小堆, 首先先将前两个元素中较大的加入最小
堆,较小的加入最大堆。然后每次添加新元素的时候,先将其与最大堆和最小堆的堆顶进行对比,
如果其大于最小堆堆顶则插入最小堆,如果其小于最大堆堆顶则插入最大堆,否则选择元素数量
较小的一堆。 在插入与向上调整结束后, 如果两堆的元素数量差大于
1(即为
2),则从元素数量
较多的一堆中取出堆顶插入另一堆,两堆相应进行向下向上调整,这样可以保证两堆元素数量始
终是平衡的。 在这种情况下,选取中位数只需要选取元素数量多
1 的一堆的堆顶,或者两堆元素
数量相同的时候选择两堆堆顶的平均数即可。
在
n>>k 的情况下,在一遍读取后取出n
个数据中最大的k
个数据
提供以下两种做法:
1, 建立一个大小为k
的最小堆, 先用数据的前
k 项创建一个堆(不用依次添加入堆中),之
后每次将读入的数据与堆顶的数据进行对比,如果比堆顶数据小则舍去,如果比堆顶数据大则将
堆顶的数据替换为读入的数据然后对其进行向下调整。考虑到
n>>k,则其时间代价
nlogk 可近似
视为
O(n)。
2, 取前k
个数据排序, 然后再取
k 个数据排序, 对两组数据进行归并合并,然后舍去后
k
个数据并继续读取硬盘数据直到数据读完。 在
n>>k 的情况下,时间代价同样近似为
O(n)。
堆,较小的加入最大堆。然后每次添加新元素的时候,先将其与最大堆和最小堆的堆顶进行对比,
如果其大于最小堆堆顶则插入最小堆,如果其小于最大堆堆顶则插入最大堆,否则选择元素数量
较小的一堆。 在插入与向上调整结束后, 如果两堆的元素数量差大于
1(即为
2),则从元素数量
较多的一堆中取出堆顶插入另一堆,两堆相应进行向下向上调整,这样可以保证两堆元素数量始
终是平衡的。 在这种情况下,选取中位数只需要选取元素数量多
1 的一堆的堆顶,或者两堆元素
数量相同的时候选择两堆堆顶的平均数即可。
# include<iostream> # include<queue> using namespace std; int main() { int p,n,m,i,j,k; cin>>p; for(i=1;i<=p;i++) { cin>>n>>m; cout<<n<<" "<<m/2+1<<endl; if(m==1) { cin>>k; cout<<k<<endl; } else { priority_queue<int, vector<int>, less<int> > pqB; priority_queue<int, vector<int>, greater<int> > pqS; cin>>n>>k; cout<<n<<" "; if(n>k) { pqB.push(k); pqS.push(n); } else { pqB.push(n); pqS.push(k); } for(j=3;j<=m;j++) { cin>>k; //insert if(k>pqS.top()) { pqS.push(k); } else if(k<pqB.top()) { pqB.push(k); } else { if(pqB.size()>pqS.size()) { pqS.push(k); } else { pqB.push(k); } } //adjust if(pqB.size()>pqS.size()+1) { while(pqB.size()>pqS.size()+1) { k=pqB.top(); pqB.pop(); pqS.push(k); } } if(pqS.size()>pqB.size()+1) { while(pqS.size()>pqB.size()+1) { k=pqS.top(); pqS.pop(); pqB.push(k); } } if(j%2==1) { if(pqB.size()>pqS.size()) { cout<<pqB.top(); } if(pqS.size()>pqB.size()) { cout<<pqS.top(); } if(j%20==19) { cout<<endl; } else { cout<<" "; } } } cout<<endl; } } return 0; }
在
n>>k 的情况下,在一遍读取后取出n
个数据中最大的k
个数据
提供以下两种做法:
1, 建立一个大小为k
的最小堆, 先用数据的前
k 项创建一个堆(不用依次添加入堆中),之
后每次将读入的数据与堆顶的数据进行对比,如果比堆顶数据小则舍去,如果比堆顶数据大则将
堆顶的数据替换为读入的数据然后对其进行向下调整。考虑到
n>>k,则其时间代价
nlogk 可近似
视为
O(n)。
2, 取前k
个数据排序, 然后再取
k 个数据排序, 对两组数据进行归并合并,然后舍去后
k
个数据并继续读取硬盘数据直到数据读完。 在
n>>k 的情况下,时间代价同样近似为
O(n)。
相关文章推荐
- 如何将数据结构和算法应用到实际之中?
- elasticsearch-hadoop使用示例
- 【有疑问,待解决】iOS 9 memory leak
- Linux inode 索引节点已满导致服务无法开启的详细解决方法
- 机器视觉学习笔记(8)——基于OpenCV的Bouguet立体校正
- COMODO冰龙浏览器
- 跟我一起写 Makefile(二)
- RichEditor for Android 是 Android 平台下一个所见即所得的文本编辑器控件。
- JS鼠标事件大全
- Eclipse懒人开发利器
- 关于使用Notepad++编译C/C++代码时,dos界面会出现中文乱码现象
- 整数的应用
- ClearEditText 可以自己清楚的edittext
- 【原】搭建Samba的简要过程
- HDFS Federation客户端(viewfs)配置攻略
- PEB和TEB资料整合
- LinkSprite携pcDuino开源生态助力西安邮电大学计算机学院科技创新与教学改革
- VTK的安装配置-使用VS2010
- ZooKeeper 初识
- 黑科技 Python脚本帮你找出微信上删除你好友的人