//作者:Ricardo.M.Tan
#include"stdafx.h"
#include"stdio.h"
#include"malloc.h"
#include"string.h"
#include<iostream>
typedef int Datatype;
typedef struct Node
{
Datatype data;
struct Node *next;
}Node, *Link;
//定义两个全局的指针变量,作用类似于中转枢纽
Link gp1 = NULL;
Link gp2 = NULL;
static Link creat()
{
Link H, p, q;
Datatype data;
int i = 1;
int NodeCount = 0;
printf("请输入将创建的链表的长度:");
scanf_s("%d", &NodeCount);
if (NodeCount <= 0)
{
printf("创建失败!");
return H;
}
H = (Link)malloc(sizeof(Node));
p = H;
printf("请输入节点 %d 的存储值:", i);
scanf_s("%d", &data);
while (--NodeCount)
{
q = (Link)malloc(sizeof(Node));
p->next = q;
q->data = data;
p = q;
printf("请输入节点 %d 的存储值:", ++i);
scanf_s("%d", &data);
}
q = (Link)malloc(sizeof(Node));
p->next = q;
q->data = data;
p = q;
p->next = NULL;
return(H);
}
//求交集
Link Intersection(Link H1, Link H2){
Link head = (Link)malloc(sizeof(Datatype));
Link tmp = head, s;
tmp->next = NULL;
Link p1 = H1->next, p2 = H2->next;//p1,p2分别指向两张链表的第一个存储位置
while (p1 != NULL)//p1指向空结束
{
while (p2 != NULL)//p2指向空结束
{
if (p2->data == p1->data)
{
s = (Link)malloc(sizeof(Datatype));
s->data = p1->data;
s->next = NULL;
tmp->next = s;
tmp = s;
break;
}
p2 = p2->next;//p2前移,循环遍历
}
p1 = p1->next;
p2 = H2->next;//重置p2的指向
}
return head;
}
//求并集
Link UnionSet(Link head1, Link head2)
{
Link head = (Link)malloc(sizeof(Node));
head->next = NULL;
Link tail = head;
Link InS = Intersection(head1, head2);//接收返回值
Link s, p1 = head1->next, p2 = head2->next, p3 = InS->next;
//遍历第一张链表并复制,以便接下来链接
while (p1)
{
s = (Link)malloc(sizeof(Node));
s->data = p1->data;
s->next = tail->next;
tail->next = s;
tail = s;
p1 = p1->next;
}
//接上面复制链表,将不是交集里含有的数据写入,类似链表插入
while (p2)
{
while (p3)//此循环用于遍历交集,判断p2指向的存储单元的存储值是否在交集中出现
{
if (p2->data == p3->data)
break;//终止此层循环,跳出前不会执行下一句
p3 = p3->next;//条件不成立则p3指针前移
}
//若上面的执行后,p2指向的存储单元的存储值没在交集中出现,此时的p3指向NULL,若出现,p3将被重置,不写入
if (!p3)//逻辑非运算(!),即当p3=NULL时,!p3=1,为真值(true),执行语句块,反之,当p3!=NULL时,!p3=0,为假值(false),不执行语句块
{
s = (Link)malloc(sizeof(Node));
s->data = p2->data;
s->next = tail->next;
tail->next = s;
tail = s;
}
p3 = InS->next;/*重置p3的指向*/
p2 = p2->next;/*p2指针前移,循环遍历第二张链表*/
}
return head;
}
//一般输出链表
void op(Link head)
{
Link p;
p = head;
while (p->next != NULL)
{
printf("%4d", p->next->data);
p = p->next;
}
}
//用于输出集合(比op()函数多了:1、空链表的判断 2、统计集合中元素个数)
void Print(Link head)
{
Link p = head->next;
int count = 0;
if (p == NULL)
{
printf("空集!\n");
return;
}
while (p)
{
printf("%3d", p->data);
count++;
p = p->next;
}
printf("(共%d个数据)\n", count);
}
//主函数入口
int main()
{
int flag = 1;
int count = 1;//用于执行控制
printf("----------------------\n提示:请先创建链表!!!\n----------------------\n");
while (flag)
{
printf("\t\t 1--创建2张新链表\n");
printf("\t\t 2--求交集\n");
printf("\t\t 3--求并集\n");
printf("\t\t 0--退出程序\n");
printf("请选择序号:");
scanf("%d", &flag);
//简单处理异常
if (flag>3){
printf("----------------------------\n警告:指令表不包含该序号!!!\n----------------------------\n");
}
else{
if (flag>count){
count = 4;
printf("----------------------------------------\n警告:还未创建链表,自动跳转到创建链表!!!\n----------------------------------------\n");
goto lable;
}
switch (flag)
{
lable:
case1 :
{
printf("创建第一张链表\n");
gp1 = creat();
printf("新建链表:");
op(gp1);
printf("\n");
printf("\n创建第二张链表\n");
gp2 = creat();
printf("新建链表:");
op(gp2);
printf("\n\n");
}
break;
case 2:
{
printf("\n交集为:");
Link InS = Intersection(gp1, gp2);
Print(InS);
printf("\n\n");
}
break;
case 3:
{
printf("\n并集为:");
Link Union = UnionSet(gp1, gp2);
Print(Union);
printf("\n\n");
}
break;
case 0:
break;
default:
printf("警告,错误!!!\n");
break;
}
}
}
//system("pause");
return 0;
}