多路归并排序
来源:互联网 发布:傲天海网络机顶盒升级 编辑:程序博客网 时间:2024/05/31 13:14
我们有如下一个问题:对于若干个长度相同的序列,将其合并成一个有序的序列。
暴力的方法显然是不可取的,这里可以利用优先队列来处理这个问题。首先从简单的开始,对于2路归并排序,设两个序列为{A},{B},将{A},{B}排序,有
A1<=A2<=A3<=...<=An
B1<=B2<=B3<=...<=Bn
建立一个优先队列,队列中首先存入元素(A1,0),(B1,1),其中标志0,1分别表示元素中的值属于第一个序列还是第二个序列,那么第一次从队列中取出的即是此刻的最小值,这时候我们再将取出元素所在的序列的下一个元素放入队列,例如首先取出的是(A1,0),那么放入队列中的即是(A2,0),这为什么是正确的呢?因为对于A1,B1来说,若取出的是A1,那么A1<B1,于是又A1<B1<B2,那么下一个比较的必然是A2和B1,绝不可能取出时B2,于是我们加入(A2,0)。
说到这里k路归并排序的算法也就呼之欲出了,很显然每次放入的元素加上一个序列的列号,然后再优先队列里面操作即可。算法的复杂度:假设一共有n个元素,有k个序列,每次存取复杂度为logk(用C++的STL即可),总的复杂度为O(nlogk)。
c++实现:
- struct Item{
- int v,num;
- Item(int v,int num):v(v),num(num){}
- bool operator < (const Item& a)const{
- return v>a.v;
- }
- };
- void merge(int* A,int* B,int* C,int n){
- priority_queue<Item> q;
- q.push(Item(A[0],0));
- q.push(Item(B[0],1));
- int cnt1=0,cnt2=0;//记录序列1和2的指针位置
- for(int i=0;i<n;i++){
- Item cur=q.front();q.pop();
- C[i]=cur.v;
- if(cur.num==0){
- if(cnt1<n)q.push(Item(A[++cnt1],0));
- else q.push(Item(B[++cnt2],1));
- }else{
- if(cnt2<n)q.push(Item(B[++cnt2],1));
- else q.push(Item(A[++cnt1],0));
- }
- }
- }
问题举例:
有这样k个序列,A1,A2,...,An,
B1,B2,...,Bn,
....
每一个序列中取一个元素,求这k个元素的和,共有k^k个和,求最小的k的和,
首先还是看两个序列:A1+B1<=A1+B2<=...<=A1+Bn
A2+B1<=A2+B2<=...<=A2+Bn
...
An+B1<=An+B2<=...<=An+Bn
那么对上述序列进行归并排序即可求得答案,注意的是我们用二元组(s,b)来表示一个元素,s是和,b是B的下标,那么下一次要存入的元素即是(s-B[b]+B[b+1],b+1)
代码如下:
- struct Item{
- int s,b;
- Item(int s,int b):s(s),b(b){}
- bool operator < (const Item& a) const{
- return s>a.s;
- }
- };
- void merge(int* A,int* B,int* C,int n){
- priority_queue<Item> q;
- for(int i=0;i<n;i++)
- q.push(Item(A[i]+B[0],0));
- for(int i=0;i<n;i++){
- Item head=q.top();
- q.pop();
- C[i]=head.s;
- int b=head.b;
- if(b+1<n)q.push(Item(head.s-B[b]+B[b+1],b+1));
- }
- }
- 多路归并排序
- 多路归并排序
- 多路归并排序
- 多路归并排序
- 多路归并排序
- 多路归并排序
- 数据结构 外部排序 多路归并排序
- 归并排序:二路归并
- 归并排序--二路归并
- 归并排序(2-路归并排序)
- 归并排序、二路归并排序
- 位图排序、多路归并排序-应对磁盘文件排序
- 二路和多路归并排序
- 多路归并排序【JAVA实现】
- 大数据多路归并排序
- 败者树 多路归并排序
- 大数据多路归并排序
- 大数据多路归并排序
- 黑马程序员——Java 包及访问控制权限
- PHP截取字符串
- ios真机调试时:error fail to launch **
- 1-2:字符串插入
- JUnit4注解测试SSH
- 多路归并排序
- valgrind 的使用简介
- 冒泡
- 搜狗浏览器搜集用户隐私遭泄露
- Python strip lstrip rstrip使用方法
- C++ 字符串操作经验集
- IOS解压缩和压缩文件
- SQL Server Profiler -- T-sql, sql监视利器
- 游戏服务器架构