算法(时间复杂度为O(nlgk)的k有序链(从小到大)表合并为一个有序链表

4 篇文章 0 订阅
3 篇文章 0 订阅

问题描述:

                设计时间复杂度为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.

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值