您的位置:首页 > 其它

使用最小堆来完成k路归并 6.5-8

2015-08-18 17:29 204 查看
感谢: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=2*i+1;
int right=2*i+2;
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-1)/2;i>=0;--i){
min_heapify(a,i,n);
}
}

int heap_extract_min(pNode *a,int n)//获取堆的最小值,并更新堆
{
int min_value=a[0]->value;
if(a[0]->next!=NULL){
a[0]=a[0]->next;
}else{
a[0]->value=numeric_limits<int>::max();
}
min_heapify(a,0,n);
return min_value;
}

int main()
{
srand(time(NULL));
int k;
while (k=(rand()%6),k<3 || k>6);//k个链表
int *size=new int[k];//每个链表的大小,不含首元素
node *ptr;//节点指针
pNode *pn=new pNode[k];//对k个链表初始化
for(int i=0;i<k;++i){//k个链表的头节点
pn[i]=new node;//初始化第i个链表
pn[i]->value=numeric_limits<int>::min();
pn[i]->next=NULL;
while (size[i]=(rand()%10),size[i]<4);//第i个链表有size个元素
for(int j=0;j<size[i];++j){
ptr=new node;
ptr->value=rand()%101-50;
ptr->next=NULL;
insert_node(pn[i],ptr);
}
}

for(int i=0;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=0;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=0;
for(int i=0;i<k;++i){//获取k个堆的元素总数
size_sum+=size[i];
}
int min_val;//存储每次的最小值
for(int i=0;i<size_sum;++i){
min_val=heap_extract_min(min_heap,k);
cout<<min_val<<"\t";
}
cout<<endl;

delete [] size;
for(int i=0;i<k;++i){
delete [] pn[i];
}
delete[]pn;
delete[] min_heap;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: