实验内容
集合的并、交和算差运算
基本内容:
编写一个能完成集合的交、并和差运算的程序。要求:
(1)集合的元素限定为小写字母字符 [‘a’..’z’]。
(2)分别用数组和单向链表表示集合。
选作内容:
(1)集合的元素判定和子集判定运算。
(2)求集合的补集。
(3)集合的混合运算表达式求值。
(4)集合的元素类型推广到其他类型,甚至任意类型。
- 数组
实验思路:
将两个集合输入进两个数组中,
并:将第一个数组对第二个数组进行遍历,如果发现两个数组中有相同的元素就将这个元素赋值为’0’,同时将第一个数组中的数值赋值进并目标数组,在将第二个数组的数值不是’0’的字符赋值进并目标数组。
交:用第一个数组遍历第二个数组,如果第一个数组的数与第二个数组有相等,用一个变量记录这个现象,从而将这个数组中的元素赋值进交数组。
差:将第一个集合对第二个数组遍历,一旦发现有相同的,则将第一个数组中遍历的数删去(也就是将该数组值定为'0')将第一个集合复制数组未被删去的(非'0'的)赋值进差数组。
代码
#include <stdio.h>
#include <stdlib.h>
int main()
{
char a[26]={'\0'}/*第一个集合数组*/,b[26]={'\0'}/*第二个集合数组*/;
char x[26]={'\0'}/*并目标数组*/,y[26]={'\0'}/*交目标数组*/,z[26]={'\0'}/*差目标数组*/;
char d[26],e[26],f[26],g[26],m[26],n[26];/*复制数组*/
int i=0,j=0,k=0,q=0;
printf("请输入第一个集合:");
for (; i<26; i++)/*遍历输入第一个集合数组*/
{
scanf("%c",&a[i]);
if (a[i]=='\n')
{
a[i]='\0';
break;
}
}
printf("请输入第二个集合:");
for (i=0; i<26; i++)/*遍历输入第二个集合数组*/
{
scanf("%c",&b[i]);
if (b[i]=='\n')
{
b[i]='\0';
break;
}
}
/*并运算*/
copyp(a,d);/*将数组a复制一份到数组d*/
copyp(b,e);/*将数组b复制一份数组e*/
for (i=0; i<26; i++)
{
if (d[i]=='\0')
{
k=i;
break;
}
for (j=0; j<26; j++)
{
if (d[i]==e[j])e[j]='0';
}
x[i]=d[i];
}/*将第二个集合复制数组遍历将与第一个数组重复的删去(也就是将该数组值定为'0'),并将第一集合的复制数组赋值进并数组*/
for (i=0; i<26; i++)
{
if (e[i]=='\0')break;
if (e[i]!='0')
{
x[k]=e[i];
x[k+1]='\0';
k++;
}
}/*将第二个集合复制数组未被删去的(非'0'的)赋值进并数组*/
printf("并集合:");
print(x);
printf("\n");
/*交运算*/
copyp(a,f);/*将数组a复制一份到数组f*/
copyp(b,g);/*将数组b复制一份到数组g*/
k=0;
for (i=0; i<26; i++)
{
if (f[i]=='\0')break;
for (j=0; j<26; j++)
{
if (f[i]==g[j])
{
q=1;
}
}
if(q==1)
{
y[k]=f[i];
y[k+1]='\0';
k++;
}
q=0;/*重置变量*/
}/*用第一个数组遍历第二个数组,如果第一个数组的数与第二个数组有相等,用一个变量记录这个现象,从而将这个变量赋值进交数组*/
printf("交集合:");
print(y);
printf("\n");
/*差运算*/
copyp(a,m);/*将数组a复制一份到数组m*/
copyp(b,n);/*将数组b复制一份数组n*/
k=0;
for (i=0; i<26; i++)
{
if (m[i]=='\0')break;
for (j=0; j<26; j++)
{
if (m[i]==n[j])m[i]='0';
}
}/*将第一个集合对第二个数组遍历,一旦发现有相同的,则将第一个数组中遍历的数删去(也就是将该数组值定为'0')*/
for (i=0; i<26; i++)
{
if (m[i]=='\0')break;
if (m[i]!='0')
{
z[k]=m[i];
z[k+1]='\0';
k++;
}
}/*将第一个集合复制数组未被删去的(非'0'的)赋值进差数组*/
printf("差集合:");
print(z);
printf("\n");
}
void copyp(char *a,char *b)/*复制数组函数*/
{
int i=0;
for (; i<26; i++)
{
b[i]=a[i];
}
}
void print(char * a)/*打印数组函数*/
{
int i=0;
for (; i<26; i++)
{
if (a[i]=='\0')break;
printf("%c",a[i]);
}
}
运行结果:
第一组:
输入数据:
第一个集合:abcdefg
第二个集合:acdbio
输出结果:
第一组:
输入数据:
第一个集合:afh
第二个集合:eio
输出结果:
- 链表
实验思路:
将两个集合输入进两个链表中,链表比较特殊,链表的结构体由一个整型变量和集合元素组成。
并:将第一个链表对第二个链表进行遍历,如果发现两个数组中有相同的元素就将这个元素对应的整型变量赋值为1,同时将第一个链表中的数值赋值进并目标链表,在将第二个链表的数值不是1的字符赋值进并目标链表。
交:用第一个链表遍历第二个链表,如果第一个链表的数与第二个链表有相同,将该元素对应结构体中的整型变量赋值为1,将整型变量为1的赋值进目标链表
差:将第一个集合对第二个数组遍历,一旦发现有相同的,则将第一个数组中遍历的数删去(也就是将元素对应结构体中的整型变量赋值为1)将第一个集合复制数组未被删去的(非1的)赋值进差数组。
代码
#include <stdio.h>
#include <stdlib.h>
typedef struct alphabet
{
int judge;
char ch;
struct alphabet* next;
} alpha;
int main()
{
void printlink(alpha *head);
void rtz(alpha * head);
alpha *a,*b,*c/*并集合链表*/,*d/*交集合链表*/,*e/*差集合链表*/,*i/*工具链表*/,*temp/*工具链表*/;
alpha *m,*n;/*替代工具链表*/
char char1,char2;
/*建立第一个集合链表*/
a=i=(alpha *)malloc(sizeof(alpha));
a->next=NULL;
printf("请输入第一个集合:");
while(1)/*输入第一个集合链表*/
{
scanf("%c",&char1);
if (char1=='\n')break;
temp=(alpha *)malloc(sizeof(alpha));
temp->judge=0;
temp->ch=char1;
i->next=temp;
i=temp;
}
i->next=NULL;
/*建立第二个集合链表*/
b=i=(alpha *)malloc(sizeof(alpha));
b->next=NULL;
printf("请输入第二个集合:");
while(1)/*输入第二个集合链表*/
{
scanf("%c",&char2);
if (char2=='\n')break;
temp=(alpha *)malloc(sizeof(alpha));
temp->judge=0;
temp->ch=char2;
i->next=temp;
i=temp;
}
i->next=NULL;
/*并*/
m=a->next;/*用替代工具链表来代替集合链表,使集合链表的头地址符号不改变*/
n=b->next;/*用替代工具链表来代替集合链表,使集合链表的头地址符号不改变*/
c=i=(alpha *)malloc(sizeof(alpha));/*建立并集合链表*/
c->next=NULL;
while(m!=NULL)
{
while (n!=NULL)/*将第一个集合链表的复制链表对第二个集合链表的复制链表进行遍历*/
{
if(m->ch==n->ch)/*当两个值相同时,将第二个复制链表的的判断值进行赋值为1,也就是标记该数值是与第一个集合链表中相同的*/
{
n->judge = 1;
}
n=n->next;
}
n=b->next;/*将n重新调成在第二个数组链表开头的位置*/
temp=(alpha*)malloc(sizeof(alpha));
temp->judge=0;
temp->ch=m->ch;
i->next=temp;
i=temp;
m=m->next;/*将m中的元素赋值到并链表中*/
}
i->next=NULL;
n=b->next;/*将n重新调成在第二个复制链表开头的位置*/
while (n!=NULL)
{
if (n->judge!=1)/*将第二个复制链表中的除去第一个复制链表中相同的元素赋值进并链表*/
{
temp=(alpha*)malloc(sizeof(alpha));
temp->judge=0;
temp->ch=n->ch;
i->next = temp;
i=temp;
}
n=n->next;
}
i->next=NULL;
printf("并集合:");
printlink(c);
printf("\n");
/*交*/
rtz(a);/*将该链表中判断值归零*/
rtz(b);/*将该链表中判断值归零*/
m=a->next;/*用替代工具链表来代替集合链表,使集合链表的头地址符号不改变*/
n=b->next;/*用替代工具链表来代替集合链表,使集合链表的头地址符号不改变*/
while (m!=NULL)
{
while (n!=NULL)/*将第一个集合链表的复制链表对第二个集合链表的复制链表进行遍历*/
{
if (m->ch==n->ch)
{
m->judge=1;/*当两个值相同时,将第一个复制链表的的判断值进行赋值为1,也就是标记该数值是与第二个集合链表中相同的*/
}
n=n->next;
}
n=b->next;
m=m->next;
}
m=a->next;
d=i=(alpha *)malloc(sizeof(alpha));
d->next=NULL;/*建立交集合链表*/
while (m!=NULL)
{
if(m->judge==1)/*将第一个赋值链表中与第二复制链表中相同的元素赋值进交链表*/
{
temp=(alpha *)malloc(sizeof(alpha));
temp->judge=0;
temp->ch=m->ch;
i->next=temp;
i=temp;
}
m=m->next;
}
i->next=NULL;
printf("交集合:");
printlink(d);
printf("\n");
/*差*/
rtz(a);/*将该链表中判断值归零*/
rtz(b);/*将该链表中判断值归零*/
m=a->next;/*用替代工具链表来代替集合链表,使集合链表的头地址符号不改变*/
n=b->next;/*用替代工具链表来代替集合链表,使集合链表的头地址符号不改变*/
while (m!=NULL)
{
while (n!=NULL)/*将第一个集合链表的复制链表对第二个集合链表的复制链表进行遍历*/
{
if (m->ch==n->ch)
{
m->judge=1;/*当两个值相同时,将第一个复制链表的的判断值进行赋值为1,也就是标记该数值是与第二个集合链表中相同的*/
}
n=n->next;
}
n=b->next;
m=m->next;
}
m=a->next;
e=i=(alpha *)malloc(sizeof(alpha));
e->next=NULL;/*建立差集合链表*/
while (m!=NULL)
{
if(m->judge==0)/*将第一个赋值链表中除去第二复制链表中相同的元素之后所剩下的元素赋值进交链表*/
{
temp=(alpha *)malloc(sizeof(alpha));
temp->judge=0;
temp->ch=m->ch;
i->next=temp;
i=temp;
}
m=m->next;
}
i->next=NULL;
printf("差集合:");
printlink(e);
printf("\n");
return 0;
}
void printlink(alpha * head)/*打印链表函数*/
{
alpha * temp=head->next;
while (temp!=NULL)
{
printf("%c",temp->ch);
temp=temp->next;
}
return;
}
void rtz(alpha * head)/*将该链表中判断值归零函数*/
{
alpha *temp=head->next;
while (temp!=NULL)
{
temp->judge=0;
temp=temp->next;
}
return;
}
运行结果:
第一组:
输入数据:
第一个集合:abcdefg
第二个集合:acdbio
输出结果:
第一组:
输入数据:
第一个集合:afh
第二个集合:eio
输出结果: