感谢:http://blog.csdn.net/mishifangxiangdefeng/article/details/7668486

声明:供自己学习之便而收集整理

题目:请给出一个时间为O(nlgk)、用来将k个已排序链表合成一个排序链表算法。此处n为所有输入链表中元素的总数。(提示:用一个最小堆来做k路合并)

算法:

step1:取每个链表的第一个元素,构造成一个含有k个元素的堆

step2:把根结点的值记入排序结果中。

step3:判断根结点所在的链表,若该链表为空,则go to step4,否则go to step5

step4:删除根结点,调整堆,go to step2

step5:把根结点替换为原根结点所在链表中的第一个元素,调整堆,go to step 2

//基于最小堆的K路归并算法
#include <iostream>
#include <ctime>
#include <limits>
using namespace std; typedef struct node{
int value;
node *next;
}node,*pNode; void insert_node(node *head, node *nenode)//直接插入法,插入新节点
{
node *cur=head;
if(head->next==NULL){
head->next=nenode;
}else{
while ((cur->next!=NULL)&&(cur->next->value<nenode->value)){
cur=cur->next;
}
nenode->next=cur->next;
cur->next=nenode;
}
} pNode delete_first_node(node *head)//删除链表第一个有效元素
{
//node *cur=head;
pNode min_value=NULL;
if(head->next!=NULL){
/*return ;
}else{*/
min_value=head->next;
head->next=head->next->next;
}
return min_value;//链表的最小值
} void min_heapify(pNode *a,int i,int n)//维护最小堆
{
int left=*i+;
int right=*i+;
int smallest=i;
if(left<n && a[smallest]->value>a[left]->value){
smallest=left;
}
if(right<n && a[smallest]->value>a[right]->value){
smallest=right;
}
if(smallest!=i){
pNode tmp=a[i];
a[i]=a[smallest];
a[smallest]=tmp;
min_heapify(a,smallest,n);
}
} void build_min_heapify(pNode *a,int n)//建立最小堆
{
for(int i=(n-)/;i>=;--i){
min_heapify(a,i,n);
}
} int heap_extract_min(pNode *a,int n)//获取堆的最小值,并更新堆
{
int min_value=a[]->value;
if(a[]->next!=NULL){
a[]=a[]->next;
}else{
a[]->value=numeric_limits<int>::max();
}
min_heapify(a,,n);
return min_value;
} int main()
{
srand(time(NULL));
int k;
while (k=(rand()%),k< || k>);//k个链表
int *size=new int[k];//每个链表的大小,不含首元素
node *ptr;//节点指针
pNode *pn=new pNode[k];//对k个链表初始化
for(int i=;i<k;++i){//k个链表的头节点
pn[i]=new node;//初始化第i个链表
pn[i]->value=numeric_limits<int>::min();
pn[i]->next=NULL;
while (size[i]=(rand()%),size[i]<);//第i个链表有size个元素
for(int j=;j<size[i];++j){
ptr=new node;
ptr->value=rand()%-;
ptr->next=NULL;
insert_node(pn[i],ptr);
}
} for(int i=;i<k;++i){//输出k个链表的元素
cout<<"list "<<i<<" has "<<size[i]<<" elements"<<endl;
node *cur=pn[i]->next;
while (cur->next!=NULL){
cout<<cur->value<<" -> ";
cur=cur->next;
}
cout<<cur->value;
cout<<endl;
}
cout<<endl; pNode *min_heap=new pNode[k];//排序堆,用来存储每个链表的第一个元素 for(int i=;i<k;++i){//删除首节点后,输出k个链表的元素
min_heap[i]=delete_first_node(pn[i]);//将最小元素存储在数组min_heap中
//cout<<min_heap[i]->value<<"\t";
/*while (pn[i]->next->next!=NULL){
cout<<pn[i]->next->value<<" -> ";
pn[i]=pn[i]->next;
}
cout<<pn[i]->next->value;
cout<<endl;*/
}
//cout<<endl; build_min_heapify(min_heap,k);//建立最小堆 int size_sum=;
for(int i=;i<k;++i){//获取k个堆的元素总数
size_sum+=size[i];
}
int min_val;//存储每次的最小值
for(int i=;i<size_sum;++i){
min_val=heap_extract_min(min_heap,k);
cout<<min_val<<"\t";
}
cout<<endl; delete [] size;
for(int i=;i<k;++i){
delete [] pn[i];
}
delete[]pn;
delete[] min_heap;
}

使用最小堆来完成k路归并 6.5-8的更多相关文章

  1. 多线程外排序解决大数据排序问题2(最小堆并行k路归并)

    转自:AIfred 事实证明外排序的效率主要依赖于磁盘,归并阶段采用K路归并可以显著减少IO量,最小堆并行k路归并,效率倍增. 二路归并的思路会导致非常多冗余的磁盘访问,两组两组合并确定的是当前的相对 ...

  2. 算法导论 6.5.9 堆实现K路归并问题

    问题: 设计一个时间复杂度为O(NlogK)的算法,它能够将K个有序链表合并为一个有序链表,这里的N为所有输入链表包含的总的元素个数 分析: 该问题为经典的利用堆完成K路归并的问题: 当K个序列满足一 ...

  3. k路归并(败者树,记录败者)

          败者树在外排序中用到,每加入一个数字时,调整树需要o(lgk),比较快.外排序过程主要分为两个阶段:(1)初始化各归并段写入硬盘,初识化的方法,可利用内排序方法还可以一种叫置换选择排序的方 ...

  4. Merge k Sorted Lists, k路归并

    import java.util.Arrays; import java.util.List; import java.util.PriorityQueue; /* class ListNode { ...

  5. HDU - 6041:I Curse Myself(Tarjan求环&K路归并)

    There is a connected undirected graph with weights on its edges. It is guaranteed that each edge app ...

  6. POJ 2442(优先队列 k路归并 堆)

    Description Given m sequences, each contains n non-negative integer. Now we may select one number fr ...

  7. 【二叉堆】k路归并问题(BSOJ1941)

    Description 有n个函数,分别为F1,F2,...,Fn.定义Fi(x)=Ai*x^2+Bi*x+Ci(x∈N*).给定这些Ai.Bi和Ci,请求出所有函数的所有函数值中最小的m个(如有重复 ...

  8. POJ-2442 Sequence K路归并问题

    题目链接:http://poj.org/problem?id=2442 问题一:K个有序表合成一个有序表,元素共有n个.用堆优化 问题二:两个序列的前n小的元素.堆优化. 这题就是问题二的扩展,每次处 ...

  9. Problem A: Assembly Required K路归并

    Problem A: Assembly Required Princess Lucy broke her old reading lamp, and needs a new one. The cast ...

随机推荐

  1. Java 数据结构之vector

    Vector 实现了一个动态数组.是可实现自动增长的对象数组. vector和arraylist的比较: 1.都是采用数组格式存储数据,索引数据块插入数据慢 2.ArrayList会比Vector快, ...

  2. installation and configuration of OpenCV4Android SDK

    http://docs.opencv.org/doc/tutorials/introduction/android_binary_package/O4A_SDK.html#running-opencv ...

  3. (译) Angular运行原理揭秘 Part 1

    当你用AngularJS写的应用越多, 你会越发的觉得它相当神奇. 之前我用AngularJS实现了相当多酷炫的效果, 所以我决定去看看它的源码, 我想这样也许我能知道它的原理. 下面是我从源码中找到 ...

  4. AOJ -0189 Convenient Location && poj 2139 Six Degrees of Cowvin Bacon (floyed求任意两点间的最短路)

    http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=78207 看懂题就好. 求某一办公室到其他办公室的最短距离. 多组输入,n表示 ...

  5. shell进行mysql统计

    array=(江苏 浙江 新疆 宁夏 广东 福建 重庆 江西 吉林 湖南 山东 云南  上海 河北 黑龙江 北京 四川 河南 山西 湖北 辽宁 安徽 陕西 广西 贵州 内蒙古 天津 甘肃 海南 青海 ...

  6. VC2005从开发MFC ActiveX ocx控件到发布到.net网站的全部过程

      开篇语:最近在弄ocx控件发布到asp.net网站上使用,就是用户在使用过程中,自动下载安装ocx控件.(此文章也是总结了网上好多人写的文章,我只是汇总一下,加上部分自己的东西,在这里感谢所有在网 ...

  7. php socket编程参考资料

    WebSocket API https://msdn.microsoft.com/library/hh673567 http://www.jnecw.com/p/1523 经朋友推荐去一家手游公司面试 ...

  8. Maven的功用所引发的哲学思想

    我们知道Maven有三个仓库 本地仓库 ~/.m2/repository/ 每一个用户也可以拥有一个本地仓库 远程仓库 中央仓库:Maven默认的远程仓库 http://repo1.maven.org ...

  9. linux VFS 内核数据结构

    <strong>简单归纳:fd只是一个整数,在open时产生.起到一个索引的作用,进程通过PCB中的文件描述符表找到该fd所指向的文件指针filp.</strong> 文件描述 ...

  10. liunx的目录结构

    linux目录结构的最顶端是/目录 我们一般都称为root目录. linux有四种文件类型,分别是普通文件,目录文件,连接文件,特殊文件,可以用file来识别. 普通文件:文本文件 二进制文件 图像文 ...