考研数据结构之线性表(1.7)——练习题之编写一个算法将m各有序(从小到大)顺序表合并成一个有序顺序表,假设所有顺序表存储在一个m行maxSize列的二维数组中(C表示)

本文介绍了一种将多个已排序的列表合并成一个有序列表的算法。通过将多个列表的合并问题转化为两个列表的合并,逐步将所有列表合并成一个。算法在合并过程中不使用额外的存储空间,直接在原数组中进行操作。

题目

编写一个算法,将m(m≥2)个有序(从小到大)顺序表合并成个有序顺序表, 假设所有顺序表存储在一个m行maxSie (maxSize 足够大)列的二维数组lists[m][maxSize]中,要求把1~m-1行所在的顺序表合并在0行所在的顺序表中,各表的长度存储在数组lens[m]中,合并过程中不另设新的顺序表存储空间。

分析

可以将m各顺序表的合并先处理为两个顺序表的合并,参考:将两个有序(非递减有序)顺序表合并成为一个顺序表,合并后的结果放到A[]中不另设新的顺序表存储空间,将lists中的1~m-1行上的顺序表逐个合并到第0行上的顺序表中,返回-1表示合并失败,返回最终表的长度表示成功。

代码

核心代码:

/* 合并A表和B表到A表中 */ 
int comb(int A[],int &na,int B[],int nb) { // 合并后na发生变化,因此使用引用型
	if(na+nb>maxSize) { // 假设maxSize是已经定义好的常量
		return -1;
	}
	int i=na,j=nb;
	while(j>0) {
		if(i==0||A[i-1]<B[j-1]) {
			A[j+i-1]=B[j-1];// 说明B[j-1]是第i+j大的元素
			j--;
		} else {
			A[j+i-1]=A[i-1];// 说明A[i-1]是第i+j大的元素
			i--;
		}
	}
	na=na+nb;
	return na;
}
 
/* 合并m各顺序表 */
/* lists[][maxSize]指的是m各顺序表,每一行是一个顺序表;lens[]表示每一个顺序表的长度;m指的是lens数组的长度 */ 
int combM(int lists[][maxSize],int lens[],int m){
	int flag;// 标记是否合并成功
	for(int i=1;i<m;i++){
		flag=comb(lists[0],lens[0],lists[i],lens[i]);// lens[i]表示第i行表的长度
		if(flag==-1){// 发现合并失败跳出循环
		break; 
		} 
	} 
	return flag;
} 

完整代码:

#include<stdio.h>
 
#define maxSize 30
 
/* 打印数组 */ 
void print(int nums[],int n) {
	printf("\n");
	for(int i=0; i<n; i++) {
		printf("%d\t",nums[i]);
	}
	printf("\n");
}

 
/* 合并A表和B表到A表中 */ 
int comb(int A[],int &na,int B[],int nb) { // 合并后na发生变化,因此使用引用型
	if(na+nb>maxSize) { // 假设maxSize是已经定义好的常量
		return -1;
	}
	int i=na,j=nb;
	while(j>0) {
		if(i==0||A[i-1]<B[j-1]) {
			A[j+i-1]=B[j-1];// 说明B[j-1]是第i+j大的元素
			j--;
		} else {
			A[j+i-1]=A[i-1];// 说明A[i-1]是第i+j大的元素
			i--;
		}
	}
	na=na+nb;
	return na;
}
 
/* 合并m各顺序表 */
/* lists[][maxSize]指的是m各顺序表,每一行是一个顺序表;lens[]表示每一个顺序表的长度;m指的是lens数组的长度 */ 
int combM(int lists[][maxSize],int lens[],int m){
	int flag;// 标记是否合并成功
	for(int i=1;i<m;i++){
		flag=comb(lists[0],lens[0],lists[i],lens[i]);// lens[i]表示第i行表的长度
		if(flag==-1){// 发现合并失败跳出循环
		break; 
		} 
	} 
	return flag;
} 
 
int main() {
	int lists[][maxSize]={{1,2,3,4,5,6},{7,8,9},{10,12,15,16},{19},{20,21}};
	int lens[]={6,3,4,1,2};
	int m=5;
 
	combM(lists,lens,m);
	print(lists[0],lens[0]);
 
	return 0;
}

运行结果:

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值