数据结构与算法(4)——合并线性表及合并有序表

1 合并线性表

将线性表Lb中的元素逐个取出,判断其是否在线性表La中,如果不在,将其插入到线性表La,具体算法如下。

Status List_Union(SqLisrPtr La, SqLisrPtr Lb)
{
	ElemType elem;
	Status status;
	int i,j;
	int len = List_Size(Lb);

	for (i = 0; i < len; i++)
	{
		//从线性表Lb中取出元素
		List_Retrieve(Lb, i, &elem);
		//判断是否存在于La中
		status = List_Locate(La, elem, &j);
		//不存在,插入
		if (status != success)
		{
			status = List_Insert(La, 0, elem);
			//插入失败,退出
			if (status != success)
			{
				break;
			}
		}
	}

	return  status;
}

该算法必须在线性表基本操作List_Size,List_Retrieve,List_Locate和List_Insert等函数实现后,才能在计算机中调用并实际运行。运用该算法最坏的情况是Lb中的所有元素都不在La中,取出Lb第一个元素后需要将其与La中的所有m个元素进行m次比较,第二个元素进行m+1次比较,以此类推,最后一个元素进行m+n-1次比较。因此,总的比较次数为m + (m+1) + … + (m+n-1) = mn + n(n - 1)/2,时间复杂度为O(mn+n * n),若m和n同量级,算法复杂度为O(n * n)。

2 合并有序表

不破坏原链表算法:依次扫描La和Lb中的元素,比较当前元素的值,将较小的元素插入到Lc中。如此反复,直到一个线性表扫描完毕,然后将未完成的线性表余下的元素逐个插入到Lc表尾。

Status List_Merge(SqListPtr La, SqListPtr Lb, SqListPtr Lc)
{
	ElemType elem1, elem2;
	int i = 0, j = 0, k = 0;
	int n = List_Size(La), m = List_Size(Lb);
	Status status = List_Init(Lc);

	while (i < n && j < m)
	{
		List_Retrive(La, i, &elem1);
		List_Retrive(Lb, j, &elem2);
		if (elem1 < elem2)
		{
			status = List_Insert(Lc, k, elem1);
			i++;
		}
		else
		{
			status = List_Insert(Lc, k, elem2);
			j++;
		}
		k++;
	}
	while (i < n)
	{
		List_Retrive(La, i, &elem1);
		status = List_Insert(Lc, k, elem1);
		i++;
		k++;
	}
	while (j < m)
	{
		List_Retrive(Lb, j, &elem2);
		status = List_Insert(Lc, k, elem2);
		j++;
		k++;
	}

	return status;
}

破坏原链表算法:快速简单粗暴,pc指向La的头结点,pa和pb分别指向La和Lb的第一个元素,比较pa->elem和pb->elem,取较小的元素的指针作为pc的next,并移动到下一个位置。直到pa或pb指向NULL,将pc指向另一个未完成的链表。

void List_Merge(SqListPtr La, SqListPtr Lb, SqListPtr Lc)
{
	Ptr pa, pb, pc, tp;

	pa = (*La)->next;
	pb = (*Lb)->next;
	pc = (*La);

	while (pa && pb)
	{
		if (pa->elem < pb->elem)
		{
			pc->next = pa;
			pc = pa;
			pa = pa->next;
		}
		else if (pa->elem > pb->elem)
		{
			pc->next = pb;
			pc = pb;
			pb = pb->next;
		}
		else
		{
			tp = pb;
			pc->next = pa;
			pc = pa;
			pa = pa->next;
			pb = pb->next;
			free(tp);
			tp = NULL;
		}
	}
	pc->next = pa ? pa : pb;
	free(*Lb);
	*Lc = *La;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值