①用单链表来实现结合的基本运算,首先用的是单链表所以我们就先给它创建一个头结点并且为它分配空间,而结点的结构体中定义了两个属性 data域和next指针域。
②实现集合元素的插入。我用的是单链表头插法的方法,先创建一个新的结点用于输入值然后插入到线性链表中去,然后依次挨个的在头部插入,这里需要注意的是线性链表的头结点next指针域的指向“ p->next=L->next; L->next=p;”。
③实现集合元素的输出。定义一个具有结点结构的指针p来指向头结点的next指针域,然后用一个while循环条件是“当p指针指向的结点的指针域为空时就停止循环”,用p指针来遍历线性链表,然后打印输出每个结点数据 “p=p->nex”为了实现遍历p指针每次要指向下一个结点,直至指向的内容为空就结束。当然在此过程进行中也要判断该链表是否为空链表。
④链表的清空。先判断是否为空表,然后在进行清空,在清空时 要实现断链的操作然后将断链出来的结点给释放掉,锻炼操作“q=p; p=q->next; ”将q结点断出来。在最后一定要记得将L线性链表的next指针域 置为 NULL 空,这样才算是真正的清空。
⑤实现两个集合的并集 并在该过程中除去重复的元素。首先要判断Lc链表是否为空如果Lc链表不为空则就要进行链表清空,然后 指针p控制扫描La的每一个结点(元素)指针q控制扫描链表Lc的每一个结点(元素),如果La中没找到与Lc链表中相同的结点时,就把La上结点在Lc上插入(把集合La的元素填入集合Lc)并采用头插法的方式来进行。将Lb中的元素填入Lc中道理跟La操作相同
⑥实现两个集合的交集,并在该过程中除去重复的元素。跟并集一样要先判断Lc链表是否为空,然后让p指针首先指向La的指针域,让q指针首先指向Lb的指针域,让s指针首先指向Lc的指针域
while(q!=NULL)
{
if(q->data==p->data) //如果找到了La与Lb相同的元素 就退出
break;
else
q=q->next; //如果没有找到就继续向下遍历
}
如果q!=空 表示找到了La与Lb共同的元素,此时再与Lc中的元素进行比较,if(s==NULL) //s==NULL表示:s指针指向了空 意味着没找到与Lc里面相同的重复元素 然后就执行插入操作。
⑦实现两个集合的差集的操作与上面两个操作类似只不过中间的一些运算条件与要变更一下,将if(q!=NULL)变为if(q==NULL)就行了。
总的来说线性表它的特点就是它存在明显的先后关系,可以用动态数组或单链表的形式来方便实现,但需要注意的是连接先后关系的纽带要找准来找到位置的方法从而确定先后关系然后进行一系列的运算。
代码如下:
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR -1
typedef int ElemType;
typedef int Status;
typedef struct LNode{
ElemType data;
struct LNode *next;
} LNode,*LinkList;
//实现创建一个头结点
Status InitList_L(LinkList &L)
{
LinkList p;
p=(LinkList)malloc(sizeof(LNode));
if(!p)
return ERROR; //分配空间没有成功 返回ERROR
L=p;
L->next=NULL;
return OK;
}
//操作的功能菜单
void menu()
{
printf("************单链表(头插法)集合运算************\n\n");
printf("\t\t1.集合A数据输入\n\n");
printf("\t\t2.集合B数据输入\n\n");
printf("\t\t3.集合A数据显示\n\n");
printf("\t\t4.集合B数据显示\n\n");
printf("\t\t5.集合A和集合B的并集\n\n");
printf("\t\t6.集合A和集合B的交集\n\n");
printf("\t\t7.集合A和集合B的差集\n\n");
printf("\t\t0.退出系统\n\n");
printf("************单链表(头插法)集合运算************\n");
printf("请输入选项:");
}
//实现集合元素的输入
Status InputLinkList_L(LinkList &L,int n) //给集合输入数据采用单链表头插法
{
LinkList p;
int i=1;
printf("单链表头插法!\n");
while(i<=n)
{
printf("第%d个数据\n",i);
p=(LinkList)malloc(sizeof(LNode)); //创建一个新的结点用于输入值然后插入到线性链表中
if(p)
{
scanf("%d",&(p->data));
p->next=L->next; //插入到头部
L->next=p;
}
else
return ERROR;
i++;
}
return OK;
}
//实现集合元素的输出
void OutputLinkList_L(LinkList L) //输出集合的数据
{
LinkList p; //定义一个指针p
int i=0;
p=L->next; //p指针指向头结点的指针域
while(p!=NULL) //当p指针指向的结点的指针域为空时就停止循环
{
i++;
printf("第%d个数据为:",i);
printf("%d\n",p->data); //用p指针来遍历线性链表,然后打印输出每个结点数据
p=p->next; //为了实现遍历p指针每次要指向下一个结点,直至指向的内容为空就结束
}
if(i==0)
printf("\n空链表,数据个数为 0.\n");
else
printf("链表的数据总数为:%d\n",i);
}
//实现链表的清空
Status ClearList_L(LinkList &L)
{
LinkList p,q; //定义两个指针p,q
p=L->next;
if(!p) //如果p指向的链表L是一个空表 就直接返回OK(1)
return OK;
while(p) //当p指向的链表L不是空表 则进行以下语句
{
q=p; //表示指向头结点下的第一个结点
p=q->next; //实现对 q 结点 进行断链
free(q); //释放链表结点的空间
}
L->next=NULL; //将L链表的next指针域 置为 NULL 空
return OK;
}
//实现两个集合的并集 并在该过程中除去重复的元素
void Union(LinkList La,LinkList Lb,LinkList &Lc)
{
LinkList p,q,s;
if(Lc->next)
ClearList_L(Lc); //如果Lc链表不为空则就要进行链表清空
p=La->next; //指针p控制扫描La的每一个结点(元素)
while(p!=NULL)
{
q=Lc->next; //指针q控制扫描链表Lc的每一个结点(元素)
while(q && (q->data != p->data))
q=q->next;
if(!q) //La中没找到与Lc链表中相同的结点时,就把La上结点在Lc上插入(把集合La的元素填入集合Lc)
{
s=(LinkList)malloc(sizeof(LNode));
s->data=p->data;
s->next=Lc->next; //插入到头部
Lc->next=s;
}
p=p->next; //指向下一个结点
}
p=Lb->next;
while(p!=NULL)
{
q=Lc->next;
while(q && (q->data != p->data)) //如果找到Lb中的元素与Lc中的元素相同则就继续循环否则就结束循环
q=q->next;
if(!q) //满足没找到相同元素的情况
{
s=(LinkList)malloc(sizeof(LNode)); //创建一个新的结点
s->data=p->data; //将Lb中的元素赋给s结点
s->next=Lc->next; //然后插入到Lc表的头部
Lc->next=s;
}
p=p->next;
}
}
//实现两个集合的交集,并在该过程中除去重复的元素
void Intersection(LinkList La,LinkList Lb,LinkList &Lc)
{
LinkList p,q,s,k;
if(Lc->next)
ClearList_L(Lc);
p=La->next; //让p指针首先指向La的指针域
while(p!=NULL)
{
q=Lb->next;
while(q!=NULL)
{
if(q->data==p->data) //如果找到了La与Lb相同的元素 就退出
break;
else
q=q->next;
}
if(q!=NULL) //q!=空 表示找到了La与Lb共同的元素
{
s=Lc->next;
while(s!=NULL)
{
if(s->data==p->data) //如果在Lc中找到相同重复的元素 就break,开始下一个元素的对比
break;
else
s=s->next;
}
if(s==NULL) //s==NULL表示:s指针指向了空 意味着没找到与Lc里面相同的重复元素 然后就执行插入操作
{
k=(LinkList)malloc(sizeof(LNode));
k->data=p->data;
k->next=Lc->next;
Lc->next=k;
}
}
p=p->next; //指向下一个结点
}
}
//实现两个集合的差集
void Difference(LinkList La,LinkList Lb,LinkList &Lc)
{
LinkList p,q,s,k;
if(Lc->next)
ClearList_L(Lc); //实现链表Lc的清空
p=La->next;
while(p!=NULL)
{
q=Lb->next;
while(q!=NULL)
{
if(q->data==p->data)
break;
else
q=q->next;
}
if(q==NULL) //q == 空 表示La与Lb元素对比 在Lb中没有发现有与La中相同的元素
{
s=Lc->next;
while(s!=NULL)
{
if(s->data==p->data)
break;
else
s=s->next;
}
if(s==NULL) //s == 空 表示在链表Lc中没有找到重复的元素
{
k=(LinkList)malloc(sizeof(LNode)); //创建一个新的结点 用于赋值插入
k->data=p->data;
k->next=Lc->next; //插入到Lc头部
Lc->next=k;
}
}
p=p->next;
}
}
//主函数部分
void main()
{
LinkList La,Lb,Lc;
int choice;
int num;
InitList_L(La);
InitList_L(Lb);
InitList_L(Lc);
while(1)
{
menu();
scanf("%d",&choice);
switch(choice)
{
case 1:
printf("需要输入几个数据:");
scanf("%d",&num);
InputLinkList_L(La,num);
getchar();getchar();system("cls"); //回车清屏操作
break;
case 2:
printf("需要输入几个数据:");
scanf("%d",&num);
InputLinkList_L(Lb,num);
getchar();getchar();system("cls");
break;
case 3:
printf("集合A数据:\n");
OutputLinkList_L(La);
getchar();getchar();system("cls");
break;
case 4:
printf("集合B数据:\n");
OutputLinkList_L(Lb);
getchar();getchar();system("cls");
break;
case 5:
printf("集合A和集合B的并集为:\n");
Union(La,Lb,Lc);
OutputLinkList_L(Lc);
getchar();getchar();system("cls");
break;
case 6:
printf("集合A和集合B的交集为:\n");
Intersection(La,Lb,Lc);
OutputLinkList_L(Lc);
getchar();getchar();system("cls");
break;
case 7:
printf("集合A和集合B的差集为:\n");
Difference(La,Lb,Lc);
OutputLinkList_L(Lc);
getchar();getchar();system("cls");
break;
case 0:
printf("欢迎使用,下次再见!\n");
exit(0);
default:
printf("输入选项有误!请输入0~7\n");
getchar();getchar();system("cls");
}
}
}