前言
好久没有写C语言的题目了,毕竟现在在学习数据结构,还是要练习c++的,上课的时候老师提到一个万能头文件#include<bits/stdc++.h>
今天在一个平台练习C语言的时候正好使用这个文件头,感觉挺轻松的,省去很多头文件,接下来对题目进行简单的分析。
题目描述:集合union
图一:题目
题目描述
假设利用两个线性表LA和LB分别表示两个集合A和B(即:线性表中的数据元素即为集合中的成员),现要求一个新的集合A=A∪B。这就要求对线性表
做如下操作:扩大线性表LA,将存在于线性表LB中而不存在于线性表LA中的数据元素插入到线性表LA中去。只要从线性表LB中依次取得每个元素,
并依值在线性表LA中进行查访,若不存在,则插入之。上述操作过程可用下列算法描述之。
图二:将两个列表合并的算法(C/C++描述)
上图算法中,在第8行取得集合B中的元素,然后再在第10行插入到集合A中。你的任务是先输出集合A和集合B中的元素,每个集合在一行中输出。
然后每次在将集合B中的元素取出插入到集合A尾部后输出集合A中的元素。当然你的代码可以和上面的代码不一样,只要有相同的输出即可。
输入
有多组测试数据,每组测试数据占两行。第一行是集合A,第一个整数m(0<m<=100)代表集合A起始有m个元素,后面有m个整数,代表A中的元素。
第二行是集合B,第一个整数n(0<n<=100)代表集合B起始有n个元素,后面有n个整数,代表B中的元素。每行中整数之间用一个空格隔开。
输出
每组测试数据输出n+2行:前两行分别输出集合A、集合B中的数据,后面n行是每次从B中取出元素插入到A尾部后的集合A。
每行整数之间用一个空格隔开,每组测试数据之间用一行空行隔开。
图三:题目运算时的输入
提示
提示:
1、使用数组时,给集合 A 分配的空间不小于200。因为将 B 中的元素添加到 A 中时,可能会超过 100 了。
2、利用 scanf("%d",&m) != EOF 来判断是否还有输入数据。
3、一个细节问题就是题目要求输出的格式是每行中元素之间用一个空格隔开,每组输出间用一个空行隔开。也就是说4个元素间只有3个空格,
2组输出间只有1个空行。处理方法都一样。两种方法:一是除了第一个元素,后面的每个元素之前输出个空格;二是除了最后一个元素,
前面的每个元素之后都输出一个空格。我往往采用第一种方式,因为许多编程语言中的数组都是从0开始的,
而0正是判断语句中的“假”(当然Java中不是这样的)。
总结:
本题考查的是线性表的基本操作。实际上只考察了遍历和添加操作。虽然算法中使用的是“插入”,然而本题只要求插入到链表的尾部,
因而只是添加而已。线性表按存储结构分为顺序表和链表。顺序表在插入时往往需要移动某些元素,而移动元素需要消耗大量时间。
如果插入操作次数很多的话,采用链表会好些。但由于只是插入到线性表的尾部,因而也不必移动元素。
所以采用顺序表解本题也不失为一个好方法。如果采用顺序表,事先需要分配足够的内存。题目中 m 和 n 都是不大于100的,
是不是给两个顺序表(数组实现)分配100的内存就够了呢?答案是否定的。因为将集合 B 添加到集合 A 中很可能就超过100个元素了。
还有,题目没有给定多少组测试数据,我们的方法就是判断是否读到了文件结尾。利用 scanf("%d",&m) != EOF 来作判断即可。
对于解本题的算法,题目描述中已经有了,我就不再赘述。除了基本操作以外,还要看怎么输出。
实际上就是在每次插入后使用一个循环将集合 A 中的所有元素输出即可。
题目分析
①:输入两个集合LA,LB
②:求它们的并集
1):遍历LB中的所有元素,看是否存在于LA中
2):若存在则把该元素插入到LA的末尾,并输出LA,换行
3):若不存在,则也输出LA,换行
③:一组数据结束后,换行
注意事项:
1)根据上面求并集过程,LA的输出次数与LB的元素个数有关
即:LB中有n个元素,求并集过程时LA得输出n次,若n=0则不输出
2)题目要求输入集合后,要输出该集合,若集合长度为0,也不输出
3)每次输出占一行
4)每组数据输出完后,空一行
如:
LA :1 1
LB:0
①先输出LA元素1换行;②LB没有元素,不输出;③又因为LB长度为0,所以之后的LA输出次数为0;④最后换行
LA:0
LB:0
①:首先,LA没有元素,不输出;②然后LB没有元素,不输出;③又因为LB长度为0,所以之后的LA输出次数为0;④最后换行
LA:0
LB:1 1
①首先,LA没有元素,不输出;②然后输出LB元素1换行;③LB长度为1输出一次LA换行,④最后换行
参考代码
#include<bits/stdc++.h>
typedef struct Union_{
int *elem;
int length;
int size_;
}*Union,UNION;
void creat_union(Union L);
void combin_(Union LA,Union LB);
void out_put(Union L);
int main()
{
UNION LA,LB;
while(scanf("%d",&LA.size_)!=EOF)
{
creat_union(&LA);
/*输入LB的长度*/
scanf("%d",&LB.size_);
creat_union(&LB);
/*合并两个集合*/
if(LA.size_!=0||LB.size_!=0)
combin_(&LA,&LB);
/*每组数据输出后用一行隔开*/
printf("\n");
}
return 0;
}
/*------------------------------------------------*/
void creat_union(Union L)
{
L->elem=(int *)malloc(L->size_*sizeof(int));
L->length=0;
for(int i=0;i<L->size_;i++)
{scanf("%d",&L->elem[i]);L->length++;}
/*长度不是0时才输出*/
if(L->length!=0)
out_put(L);
}
/*------------------------------------------------*/
void combin_(Union LA,Union LB)
{
int j;
/*为了避免每次插入都要分配,导致分配次数过多,所以直接给LA->elem[],重分配空间大小为
LA->length+LB->length,但这种分配可能会造成空间浪费,还有一种方法是把要插入的元素个数求出来,再分配
但浪费时间*/
if(LA->length+LB->length>LA->size_)
LA->elem=(int *)realloc(LA->elem,(LA->length+LB->length)*sizeof(int));
for(int i=0;i<LB->length;i++)
{
/*判断LB中下标为i的元素在LA中是否存在*/
for(j=0;j<LA->length;j++)
{
if(LA->elem[j]==LB->elem[i])
break;
}
/*若果不存在则把LB->elem[i]插入到LA末尾,再插入之前,先重分配空间*/
if(j==LA->length)
{
LA->elem[LA->length++]=LB->elem[i];
}
out_put(LA);
}
}
/*------------------------------------------------*/
void out_put(Union L)
{ /*除最后一个元素外,其余元素输出后都有空格*/
for(int i=0;i<L->length-1;i++)
printf("%d ",L->elem[i]);
/*输出最后一个元素*/
printf("%d\n",L->elem[L->length-1]);
}
需要注意的是:该头文件#include<bits/stdc++.h>
为C++语言所使用的,所以在提交的时候需要选择使用C++语言