集合运算.docx
《集合运算.docx》由会员分享,可在线阅读,更多相关《集合运算.docx(16页珍藏版)》请在冰豆网上搜索。
集合运算
计算机学院教学实验报告
课程名称
高级程序语言实验
成绩
教师签名
实验名称
集合基本运算
实验序号
实验日期
姓名
学号
专业
年级-班
1、实验目的及实验内容
(本次实验所涉及并要求掌握的知识;实验内容;必要的原理分析)
小题分:
1.问题描述
【问题描述】
编写一个能演示执行两个集合之间的并、交和差运算结果的程序。
【基本要求】
1)两个集合中的元素为长度不同的字符串,字符串中可包含大小写字符和数字字符,
2)程序以用户的输入数据建立集合,然后执行集合运算,分别输出结果
2.问题涉及到的知识
单链表的建立
排序算法
有序链表的合并
字符的输入
3.解决思路原理
1)输入字符,头插法建立链表
2)利用冒泡排序对链表进行排序,建立有序链表
3)将有序链表A和B进行合并成链表C后,删去相同的字符,实现集合的并运算
4)对有序链表A中每个元素进行检查,求有序链表A和B中相同的字符,实现集合的交运算
5)对有序链表A中每个元素进行检查,删去与B中字符相同的部分,实现集合的减运算
2、实验环境及实验步骤
(本次实验所使用的器件、仪器设备等的情况;具体的实验步骤)
小题分:
1.运行平台
DevC++5.11
2.实验步骤
1)查阅资料,对集合的交、并、减运算算法的一般实现方法进行大致的印象记忆
2)分析问题,分析需要的函数功能,进行模块划分
3)分析合适的数据结构,确定合适的函数返回类型
4)翻阅《数据结构》和《高级程序设计语言》检验设想的正确与否,并参考书上的实例,确定主要算法
5)进行编程
6)调试,查阅资料,修改
7)撰写实验报告,反思实验的不足
3、实验过程分析
(详细记录实验过程中发生的故障和问题,进行故障分析,说明故障排除的过程及方法。
根据具体实验,记录、整理相应的数据表格、绘制曲线、波形等)
小题分:
1.实验过程
问题:
1)对函数的传递功能不明确,导致无法成功地将数据传递下去
2)没有考虑运行效率,导致算法性能不强,连用if语句,造成程序无法顺利运算
3)没有及时释放链表内存,造成内存泄漏
4)对集合的减运算没有清晰的认识,造成减运算输出错误
5)对链表的结构不清晰,在输出链表时,漏掉头或尾数据
6)不能自动滤去非法字符(如空格、阿拉伯数字等)。
7)刚开始时曾忽略了一些变量参数的标识”&”,使调试程序浪费时间不少。
今后应重视确定参数的变量和赋值属性的区分和标识
8)格式不统一,阅读起来不流畅
解决措施:
1)翻查资料,询问同学,加深对链表的理解
2)将IF语句的判断条件转化成其他语句,实现对其判断
3)运行结果不正确时,对算法进行重复思考,寻找出正确的解决途径
2.代码主体部分
voidreaddata(LinkList*&L);//定义输入集合函数,头插法建链表
voidSortList(LinkList*&La);//对链表排序
voidDeleteSame(LinkList*&La);//删去链表中相同的节点
voidadd(LinkList*La,LinkList*Lb,LinkList*Lc);//合并有序链表La和Lb
voidintersection(LinkList*La,LinkList*Lb,LinkList*Lc);//对有序链表La和Lb求交集
voidsub(LinkList*La,LinkList*Lb);//求有序链表La减有序链表Lb
intmain();
3.数据结构分析
有序单链表
结构体
typedefstructLinkNode
{
chardata;
structLinkNode*next;
}LinkList;
4.运行结果
4、实验结果总结
(对实验结果进行分析,完成思考题目,总结实验的新的体会,并提出实验的改进意见)
小题分:
1.复杂度分析
时间复杂度O(n*n)
空间复杂度O
(1)
2.运行效率
指针需要进行动态内存分配以及及时的释放链表,在没有及时的释放内存的情况下,时而造成程序的异常,但是整体而言,程序运行速度较快
3.改进意见
1)排序算法空间复杂度小,但是并没有对冒泡排序进行优化,不适合大数据,可采用希尔排序等其他排序方式;
2)及时释放链表内存
3)从《计算机组成原理》的角度去看代码的写成,分支语句不能进行多次的重复,会造成汇编时的不便
#include
#include
typedefstructLinkNode
{
chardata;
structLinkNode*next;
}LinkList;
voidreaddata(LinkList*&L);//定义输入集合函数,头插法建链表
voidSortList(LinkList*&La);//对链表排序
voidDeleteSame(LinkList*&La);//删去链表中相同的节点
voidadd(LinkList*La,LinkList*Lb,LinkList*Lc);//合并有序链表La和Lb
voidintersection(LinkList*La,LinkList*Lb,LinkList*Lc);//对有序链表La和Lb求交集
voidsub(LinkList*La,LinkList*Lb);//求有序链表La减有序链表Lb
intmain()
{
intx=0;
LinkList*La,*Lb,*Lc;
La=(LinkList*)malloc(sizeof(LinkList));
La->next=NULL;
Lb=(LinkList*)malloc(sizeof(LinkList));
Lb->next=NULL;
Lc=(LinkList*)malloc(sizeof(LinkList));
Lc->next=NULL;
printf("请输入一个字符串集合A(可包含数字)以!
结尾\n");
readdata(La);
printf("\n");
printf("集合A排序结果是");
SortList(La);
printf("\n\n");
printf("请再输入一个字符串集合B(可包含数字)以!
结尾\n");
readdata(Lb);
printf("\n");
printf("集合B排序结果是");
SortList(Lb);
A:
printf("1.并集2.交集3.差集4.结束x.重新运算\n");
do{
printf("请选择序号\n");
scanf("%d",&x);
switch(x)
{
case1:
add(La,Lb,Lc);//调用并集函数
Lc->next=NULL;
break;
case2:
intersection(La,Lb,Lc);//调用交集函数
Lc->next=NULL;
break;
case3:
sub(La,Lb);//调用差集函数
Lc->next=NULL;
break;
case4:
break;
default:
gotoA;
}
}while(x!
=4);
system("PAUSE");
return0;
}
voidreaddata(LinkList*&L)//定义输入集合函数,头插法建链表
{
LinkList*p;
chartmp;
scanf("%c",&tmp);
while(tmp!
='!
')
{
p=(LinkList*)malloc(sizeof(LinkList));
p->data=tmp;
p->next=L->next;
L->next=p;
scanf("%c",&tmp);
}
p=L->next;
while(p!
=NULL)
{
printf("%c",p->data);
p=p->next;
}
printf("\n");
}
voidcreate(charstr[],LinkList*&L)//采用尾插法建立有序链表
{
LinkList*s,*r;
inti;
r=L;
for(i=0;str[i]!
='\0';i++)
{
s=(LinkList*)malloc(sizeof(LinkList));
s->data=str[i];
r->next=s;
r=s;
}
r->next=NULL;
}
voidSortList(LinkList*&La)//对链表排序
{
LinkList*p;
LinkList*pre,*q;
p=La->next->next;
La->next->next=NULL;
while(p!
=NULL)//冒泡排序
{
q=p->next;
pre=La;
while(pre->next!
=NULL&&pre->next->datadata)
pre=pre->next;
p->next=pre->next;
pre->next=p;
p=q;
}
p=La->next;
while(p!
=NULL)
{
printf("%c",p->data);
p=p->next;
}
printf("\n");
}
voidDeleteSame(LinkList*&La)//删去链表中相同的节点
{
LinkList*p,*q;
p=La->next;
charc1,c2;
while(p->next!
=NULL)
{
c1=p->data;
c2=p->next->data;
if(c1==c2)//如果有相同的节点,则删去其中一个
{
q=p->next;
p->next=q->next;
free(q);
}
p=p->next;
}
}
voidadd(LinkList*La,LinkList*Lb,LinkList*Lc)//合并有序链表La和Lb
{
LinkList*r,*s,*pc;
LinkList*pa=La->next;
LinkList*pb=Lb->next;//pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点
r=Lc;//r始终指向Lc的尾节点
while(pa!
=NULL&&pb!
=NULL)
{
if(pa->datadata)
//取较小者La中的元素,将pa链接在pc的后面,pa指针后移
{
s=(LinkList*)malloc(sizeof(LinkList));
s->data=pa->data;
r->next=s;r=s;
pa=pa->next;
}
elseif(pa->data>pb->data)
//取较小者Lb中的元素,将pb链接在pc的后面,pb指针后移
{
s=(LinkList*)malloc(sizeof(LinkList));
s->data=pb->data;
r->next=s;r=s;
pb=pb->next;
}
else
{
s=(LinkList*)malloc(sizeof(LinkList));
s->data=pb->data;
r->next=s;r=s;
pb=pb->next;
pa=pa->next;
}
}
while(pa!
=NULL)
{
/*if(pa->data>'z'||pa->data<'A'||pa->data<'a'||pa->data>'Z')
pa=pa->next;*/
s=(LinkList*)malloc(sizeof(LinkList));
s->data=pa->data;
r->next=s;r=s;
pa=pa->next;
}
while(pb!
=NULL)
{
/*if(pb->data>'z'||pb->data<'A'||pb->data<'a'||pb->data>'Z')
pb=pb->next;*/
s=(LinkList*)malloc(sizeof(LinkList));
s->data=pb->data;
r->next=s;r=s;
pb=pb->next;
}
r->next=NULL;
DeleteSame(Lc);
pc=Lc->next;
printf("并集为\n");
while(pc!
=NULL)
{
printf("%c",pc->data);
pc=pc->next;
}
printf("\n");
}
voidintersection(LinkList*La,LinkList*Lb,LinkList*Lc)//对有序链表La和Lb求交集
{
LinkList*pa=La->next;
LinkList*pb=Lb->next;
LinkList*r,*s,*pc;//pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点
r=Lc;//r始终指向Lc的尾节点
while(pa!
=NULL&&pb!
=NULL)
{
if(pa->data==pb->data)
{
s=(LinkList*)malloc(sizeof(LinkList));
s->data=pa->data;
r->next=s;r=s;
pa=pa->next;
}
elseif(pa->data>pb->data)
pb=pb->next;
else
pa=pa->next;
}
r->next=NULL;
DeleteSame(Lc);
pc=Lc->next;
printf("交集为\n");
while(pc!
=NULL)
{
printf("%c",pc->data);
pc=pc->next;
}
printf("\n");
}
voidsub(LinkList*La,LinkList*Lb)//求有序链表La减有序链表Lb
{
LinkList*pa,*pb,*apre;
chare;
intflag;
pa=La;
apre=La;
while(pa!
=NULL)//遍历链表La中的每一个元素
{
flag=0;
e=pa->data;
pb=Lb;//对La中的每一个元素e,都从Lb的表头开始查找
while(pb!
=NULL)
{
if(pb->data==e)//若La中的元素Lb也有,则在La中删除该元素
{
if(pa==La)//pa是表头
{
La=pa->next;
apre=pa->next;
pa=pa->next;
flag=1;
}
elseif(pa->next==NULL)//pa是表尾
{
pa=NULL;
apre->next=pa;
flag=1;
}
else//非表头元素和表尾元素
{
apre->next=pa->next;
pa=pa->next;
flag=1;
}
break;
}
elsepb=pb->next;
}
if(flag==0)
{
apre=pa;
pa=pa->next;
}
}
printf("两集合之差为(前面的字符集合减去后面的字符集合)\n");
pa=La;
while(pa!
=NULL)
{
printf("%c",pa->data);
pa=pa->next;
}
printf("\n");
}