二、集合合并
题目描述
我们的教材上讨论了一个如何使用基本运算将两个集合合并的问题。下面,我们就采用基本操作完成集合合并的操作。
问题: 线性表的合并A=A∪B
设:有两个集合A和B分别用两个线性表LA和LB表示。求一个新的集合 A=A∪B。
- 输入:两个集合
- 输出:按照要求合并后的集合。
编程要求:题目中已经给出了主函数和部分已经实现的基本操作,请阅读给出的程序,编写其他尚未完成的基本操作(基本操作的定义请参见教材)。
注意:提交代码的时候,仅需提交你编写的那三个基本操作函数即可。
前置代码:
/* PRESET CODE BEGIN - NEVER TOUCH CODE BELOW */
#include <stdio.h>
#include <stdlib.h>
#define LIST_MAX_SIZE 100 //空间初始大小
#define OK 1
#define ERROR 0
typedef int ElemType; //元素的数据类型
typedef int Status; //状态。函数返回值
typedef struct {
// ElemType elem[ LIST_MAX_SIZE ]; // 存储空间
ElemType * elem; // 存储空间
int length; // 当前元素个数
int listsize; // 能够保存的最大元素数量
} SqList;
// 以下为函数原型
Status InitList( SqList & );
Status ListInsert( SqList &, int, ElemType ); //这是需要你编写的基本操作
Status GetElem( SqList, int, ElemType & ); //这是需要你编写的基本操作
int ListLength( SqList ); //这是需要你编写的基本操作
Status ListTraverse( SqList &, void (*)( ElemType ) );
void ListUnion( SqList &, SqList );
void out( ElemType );
int equal(ElemType, ElemType );
Status LocateElem(SqList, ElemType, Status (*)(ElemType,ElemType));
// 以下为函数定义
Status InitList( SqList & L ) // 建立一个空的线性表 L
{
L.elem = (ElemType *)malloc(LIST_MAX_SIZE*sizeof(ElemType));
// if ( !L.elem ) exit(-1); // 失败则终止程序
L.length = 0; // 空表长度为0
L.listsize = LIST_MAX_SIZE;
return OK;
}
Status ListTraverse( SqList &L, void (*visit)( ElemType ) )
{ // 依次对L的每个元素调用函数visit()。若visit()失败,则操作失败
int i, L_len = ListLength( L );
ElemType e;
for ( i = 1; i <= L_len; i++ ) {
GetElem(L, i, e);
(*visit)( e );
}
return OK;
}
int equal(ElemType x, ElemType y)
{ return x==y;
}
Status LocateElem( SqList L, ElemType e,
Status (*compare)(ElemType,ElemType) )
{ //在L中查找与元素 e 满足compare() 的第 1 个元素
//返回 L 中第 1 个与 e 满足关系compare( ) 的元素的位序
int i = 1;
ElemType * p;
while ( i<=L.length ) //
if ( (*compare)(e,L.elem[i-1]) ) break;
else i++;
if ( i <= L.length ) return i; // 找到 e,返回位序i
else return 0; //若没有找到,则返回0
}
void out( ElemType e )
{ printf("%d,", e);
}
void ListUnion( SqList &La, SqList Lb ) //求 A=A∪B
{ int La_len, Lb_len, i;
ElemType e;
La_len = ListLength( La ); // 求线性表的长度
Lb_len = ListLength( Lb );
for ( i = 1; i <= Lb_len; i++ ) {
GetElem(Lb, i, e); // 取Lb中第i个数据元素赋给e
if ( !LocateElem( La, e, equal ) )
ListInsert ( La, ++La_len, e ); // La中不存在和 e 相同的数据元素,则插入
}
}
int main()
{ SqList La, Lb;
int n, i;
ElemType e;
InitList( La );
InitList( Lb );
scanf("%d", &n); //读入集合A
for ( i=0; i<n; i++ )
{ scanf("%d", &e);
ListInsert( La, i+1, e );
}
scanf("%d", &n); //读入集合B
for ( i=0; i<n; i++ )
{ scanf("%d", &e);
ListInsert( Lb, i+1, e );
}
printf("Output La:");
ListTraverse( La, out );
printf("\nOutput Lb:");
ListTraverse( Lb, out );
ListUnion( La, Lb );
printf("\nResult La:");
ListTraverse( La, out );
printf("\n");
return OK;
}
/****************
Status ListInsert( SqList &L, int i, ElemType e )
{ //在顺序线性表L中第 i (1≤i≤L.length+1)个位置之前插入元素e,
Here is wating for you.
}
Status GetElem(SqList L, int i, ElemType &e)
{
Here is wating for you.
}
int ListLength(SqList L)
{
Here is wating for you.
}
*********************/
/* PRESET CODE END - NEVER TOUCH CODE ABOVE */
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 5 1 2 3 4 5 6 3 4 5 6 7 8 | Output La:1,2,3,4,5, Output Lb:3,4,5,6,7,8, Result La:1,2,3,4,5,6,7,8,↵ | 1秒 | 64M | 0 |
测试用例 2 | 0 4 1 2 3 4 | Output La: Output Lb:1,2,3,4, Result La:1,2,3,4,↵ | 1秒 | 64M | 0 |
测试用例 3 | 5 8 9 0 1 2 6 8 9 0 3 2 1↵ | Output La:8,9,0,1,2, ↵Output Lb:8,9,0,3,2,1, Result La:8,9,0,1,2,3,↵ | 1秒 | 64M | 0 |
解题思路
操作 | 实现思路 |
---|---|
插入元素-ListInsert() | 在顺序线性表L中第 i (1≤i≤L.length+1)个位置之前插入元素e。 若 i 的输入不合法,或者存储空间已满,则返回ERROR ,表示插入失败;否则,在表尾插入新元素 e ,顺序表长度增加1,插入成功,返回OK |
按位查找-GetElem() | 获取线性表L中第 i 个位置的元素的值。 若 i 的输入不合法,则返回ERROR ,表示获取失败;否则,根据线性表随机存取的特点,获取表中物理结构第 i-1 个位置的值,返回OK |
求表长-ListLength() | 直接返回线性表L的长度即可 |
上机代码
Status ListInsert( SqList &L, int i, ElemType e )
{
if (i<1 || i>L.length+1)//判断i的范围是否有效
{
return ERROR;
}
if (L.length>=L.listsize)//判断存储空间是否已满
{
return ERROR;
}
L.elem[L.length] = e;//表尾插入新元素
L.length++;
return OK;
}
Status GetElem(SqList L, int i, ElemType &e)
{
if (i<1 || i>L.length)//判断i的范围是否有效
{
return ERROR;
}
e = L.elem[i-1];//获取第i个位置的值
return OK;
}
int ListLength(SqList L)
{
return L.length;//获取线性表的长度
}
简单拓展
这个题在 ListInsert()
插入操作时是直接通过表尾进行插入,但是对于更一般的线性表插入操作,应当为指定任意位置i
进行插入。
对于任意指定位置i
,将顺序表的第i
个元素及其后的所有元素右移一个位置,腾出一个空位置插入新元素e
,顺序表长度加1,插入成功,返回OK
。
Status ListInsert( SqList &L, int i, ElemType e )
{
if (i<1 || i>L.length+1)//判断i的范围是否有效
{
return ERROR;
}
if (L.length>=L.listsize)//判断存储空间是否已满
{
return ERROR;
}
for (int j = L.length; j >= i; j--)//将对应元素后移
{
L.elem[j] = L.elem[j-1];
}
L.elem[i-1] = e;//位置i处插入e
L.length++;
return OK;
}