c语言集合运算有菜单,C语言集合的运算



一.集合运算目的

通过对集合交集,并集,差集运算来进一步熟悉和掌握链表的创建,删除,插入等一些基本的操作。

二.集合运算内容

定义两个集合A和B:

差集 :A与B的差集就是该元素属于A集合而不属于集合。并集:A与B相结合该元素既属于A又属于B。交集:A与B相同的一部分,既属于A又属于B。其实这个运算器有两种做法,一是重新malloc空间,将它们处理后的数都专门放到一个链表中去,这样虽然简单,易操作,但是空间的复杂度就高了;二是不malloc空间,我直接用A链为主链对其操作,在其上对链表的元素进行插入,删除,等操作,空间复杂度就可以不用考虑了。

三.集合运算代码

#include

#include

#include

#include

typedef struct node

{

int data;

struct node *next;

}linklist;

linklist *initlist() //链表的初始化

{

int d;

linklist *p,*head,*q;

head=(linklist*)malloc(sizeof(linklist)); //具有头结点

head->next=NULL;

p=head;

scanf("%d",&d);

while(d)

{

q=(linklist*)malloc(sizeof(linklist));

q->data=d;

p->next=q; // 利用尾差法

p=q;

p->next=NULL;

scanf("%d",&d);

}

return head;

}

linklist *xiangjian(linklist *head1,linklist *head2) //集合的差运算

{

int flag=0;

linklist*p1,*p2,*q;

p1=head1;

p2=head1->next;

while(p2&&p2->next)

{

for(q=head2->next;q;q=q->next)

if(p2->data==q->data)

{

p1->next=p2->next;

free(p2);

p2=p1->next;

flag=1;

}

if(flag==0)

{

p1=p1->next;

p2=p2->next;

}

else

flag=0;

}

return head1;

}

linklist *hebing(linklist *head1,linklist *head2) // 集合的合并

{

int flag=0;

linklist *p,*q,*m;

p=head1->next;

while(p)

{

for(q=head2->next;q;q=q->next)

{

if(p->data==q->data)

{

flag=1;

break;

}

}

if(flag==0)

{

m=(linklist*)malloc(sizeof(linklist));

m->data=p->data;

m->next=head2->next;

head2->next=m;

}

flag=0;

p=p->next;

}

return head2;

}

linklist *jiaoji(linklist*head1,linklist *head2) // 集合的交集

{

linklist *p,*q,*m,*head;

head=(linklist*)malloc(sizeof(linklist));

head->next=NULL;

p=head1->next;

while(p)

{

for(q=head2->next;q;q=q->next)

if(q->data==p->data)

{

m=(linklist*)malloc(sizeof(linklist));

m->data=p->data;

m->next=head->next;

head->next=m;

break;

}

p=p->next;

}

return head;

}

int estimate(linklist *head) // 看链表里面是否有重复元素

{

linklist *p,*q;

if(head->next==NULL)

return 0;

for(p=head->next;p->next;p=p->next)

for(q=p->next;q;q=q->next)

if(p->data==q->data)

{

return 1;

}

return 0;

}

void print(linklist *head) //链表的输出

{

linklist *p;

p=head->next;

while(p)

{

printf("%d ",p->data);

p=p->next;

}

}

int main()

{

int x;

char ch;

linklist *head1,*head2,*head3,*head4,*head5;

printf("请输入链表1: ");

head1=initlist();

printf("请输入链表2: ");

head2=initlist();

if(estimate(head1)||estimate(head2))

{

printf("集合 1 或者 集合 2 不合法,自动退出\n");

exit(-1);

}

else

printf("\n创建列表成功\n");

Sleep(2000);

while(1)

{

system("cls");

printf("1 集合相减 \n");

printf("2 集合合并 \n");

printf("3 集合交集 \n");

printf(" 请选择(1-3)");

scanf("%d",&x);

switch(x)

{

case 1 :system("cls");

printf("输出链表1: ");

print(head1);

printf("\n 输出链表2: ");

print(head2);

head3=xiangjian(head1,head2);

printf("\n 集合相减: ");

print(head3);

printf("\n按任意继续.................\n");

getch();

break;

case 2 :system("cls");

printf("输出链表1: ");

print(head1);

printf("\n 输出链表2: ");

print(head2);

head4=hebing(head1,head2);

printf("\n 集合合并: ");

print(head4);

printf("\n按任意继续.................\n");

getch();

break;

case 3 :system("cls");

printf("输出链表1: ");

print(head1);

printf("\n 输出链表2: ");

print(head2);

head5=jiaoji(head1,head2);

printf("\n 集合交集: ");

print(head5);

printf("\n按任意继续.................\n");

getch();

break;

default:system("cls");

printf("你的输入有误 ");

printf("\n按任意继续.................\n");

getch();

break;

}

printf("\n如果想退出,请按n\n");

ch=getch();

if(ch=='n')

break;

}

printf("程序已完成,谢谢\n");

return 0;

}

四.集合运算分析

差集:将A和B链表传入差集函数xiangjian(head1,head2),定义3个指针变量,p1总是p2的前驱节点,遇到相等就把A链中的值删除了,p2和p1重新指向,用flag标记遇到相等转变一次,否则,p1和p2同时向后面移动,主要思路还是两层循环,在A链一层循环基础上让B链进行第二层循环遍历,对值进行判断。

并集:将A和B链表传入合并函数hebing (head1,head2),还是用到3个指针变量,在A链一层循环基础上让B链进行第二层循环遍历是,一遇相等的值,直接break跳出,标记flag=1;进行下一次。当遍历B链表完之后,没有相等的值,那么给m开辟空间,利用头插法插在B链表的前面,最后返回head2.

交集:将A和B链表传入交集函数jiaoji (head1,head2),对于这个函数,我重新开辟了一个链表,继续两层循环,和上面的思路一样,如果遇到相等的,就把该值放在新开辟的链表中。

五. 总结

我这次做的集合只考虑数字,用int而没有用char,如果出现字母我的就不能运行了,我也想过用字符做,我认为最应该考虑的地方输入问题,字符是一个一个读入的,连续输入就能出现95,110等多位数字,这就需要用到空格隔开处理,其他的做法和整型一样的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值