问题描述:
设计时间复杂度为O(nlgk)的算法,它能够将k个有序链表合并为一个有序链表,这里的n是所有输入链表包含的总元素个数。
问题分析:
采用最小堆的方法求解。1.取k个链表的第一个元素,构成一个最小堆。
2.取掉最小堆的根及数组下标为零的元素放入大小为n的数组中,再在所取根元素所在的链表中去下一个元素放入堆的根位置,如果链表有一个为空,则堆大小减一,然后维持最小堆。
3.重复步骤2,直到所有链为空。
#include "stdafx.h"
#include<iostream>
using namespace std;
struct LNode
{
int a;
LNode *next;
};
LNode *pr;//记录链表中下标为x的元素位置(设为全局变量)
int Size(LNode * p)//链表长度
{
int i=0;
while(p&&p->next)
{
i++;
p=p->next;
}
return i;
}
LNode*&Locate(LNode *p,int x)//返回链表中指向x位置的元素
{
pr=p->next;
while(pr&&x>0)
{
pr=pr->next;
x--;
}
return pr;
}
void CreateLNode(LNode* &L,int n)//创建链表
{
L=new LNode();
L->next=NULL;
for(int i=0;i<n;i++)
{
LNode *p=new LNode();
cin>>p->a;
p->next=L->next;
L->next=p;
}
}
void Create_Empty_LNode(LNode* &L,int n)//创建空链表
{
L=new LNode();
L->next=NULL;
for(int i=0;i<n;i++)
{
LNode *p=new LNode();
p->a=0;
p->next=L->next;
L->next=p;
}
}
LNode *& Locat_LNode(LNode *p[],int a,int n)//确定堆根元素属于哪个链
{
int i=0;
while(i<n)
{
LNode *pr=p[i];
while(pr&&pr->next)
{
pr=pr->next;
if(a==pr->a)
{
p[i]=pr;
return p[i];
}
}
i++;
}
}
void Keep_Min_Heapify(LNode * &a,int i,int n)//维持最小堆
{
int l=2*i;
int r=2*i+1;
int large=0;
if(l<Size(a)&&Locate(a,l)->a<Locate(a,i)->a)
{
large=l;
}
else
{
large=i;
}
if(r<Size(a)&&Locate(a,r)->a<Locate(a,i)->a)
{
large=r;
}
if(large!=i)
{
int temp=0;
temp=Locate(a,i)->a;
Locate(a,i)->a=Locate(a,large)->a;
Locate(a,large)->a=temp;
Keep_Min_Heapify(a,large,n);
}
return ;
}
void Create_Min_Heapify(LNode *&a,int n)//创建最小堆
{
for(int i=n/2;i>=0;i--)
{
Keep_Min_Heapify(a,i,n);
}
return ;
}
int _tmain(int argc, _TCHAR* argv[])
{
const int K=3;
LNode *p[K];
int n1;
cout<<"请输入第一个链表长度\n";
cin>>n1;
CreateLNode(p[0],n1);//有序输入,且为倒序构建链表.
int n2;
cout<<"请输入第二个链表长度\n";
cin>>n2;
CreateLNode(p[1],n2);//有序输入,且为倒序构建链表.
int n3;
cout<<"请输入第二个链表长度\n";
cin>>n3;
CreateLNode(p[2],n3);//有序输入,且为倒序构建链表.
int *A =new int [n1+n2+n3];//存放合并后的链表
int Alable=0;//标示A的下标
LNode * a=0;//最小堆
Create_Empty_LNode(a,K);
LNode * ar=a->next;
for(int i=0;i<K;i++)
{
LNode *pr=p[i];
pr=pr->next;
ar->a=pr->a;
ar=ar->next;
}//取链表的第一个元素存入a中
Create_Min_Heapify(a,K-1);//创建最小堆
int k=K;//记录链表个数
while(k>=1)
{
LNode *L=0;
A[Alable++]=a->next->a;
L=Locat_LNode(p,a->next->a,K);
if(L->next==NULL)
{
LNode *a1=a;
while(a1->next)
{
a1=a1->next;
}
a->next->a=a1->a;
k--;
Keep_Min_Heapify(a,0,k);
}
else
{
a->next->a=L->next->a;
if(k!=1)
{
Keep_Min_Heapify(a,0,k);
}
}
}
//2,3步程序实现
for(int i=0;i<n1+n2+n3;i++)
{
cout<<A[i]<<endl;
}
return 0;
}
注意:链表的创建为倒序创建 链表有序(从小到大)输入要从大到小 eg:链表 3,6,9 输入要是9,6,3.