数据结构课程设计——集合的交、并和差运算

news/2024/11/8 4:32:14/

集合的交、并和差运算

数据结构课程设计任务书

学生姓名:        专业班级: 软件工程

指导教师:        工作单位: 

题  目:  集合的并、交和差运算                                    

基础要求:

  1. 掌握数据结构与算法的设计方法,具备初步的独立分析和设计能力。
  2. 初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能。

3、提高综合运用所学的理论知识和方法独立分析和解决问题的能力。

主要任务:

(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)

(1)任务内容

编制一个能演示执行集合的并、交和差运算的程序。

(2)完成要求

对系统进行功能模块分析、控制模块分析;系统设计要能完成题目所要求的功能;编程简练,可用,尽可能的使系统的功能更加完善和全面;说明书、流程图要清楚;提高学生的论文写作能力;特别要求自己独立完成;在基本要求达到后,可进行创新设计,如改善算法性能、友好的人机界面。

(3)撰写课程设计报告

报告格式按附件要求打印与写课程设计报告;论文包括目录、正文、小结、参考文献、附录等;课程设计论文装订按学校的统一要求完成。

时间安排:

内容                  天数             地点

构思及收集资料          1              图书馆

编码与调试              3              图书馆

撰写论文                1              图书馆

指导教师签名:                             

完整资料一键获取私信我:

 

  • 问题分析和任务定义

1.1 问题的描述

编制一个能演示执行集合的并、交和差运算的程序。

1.2 基本要求

(1) 集合的元素限定为小写字母字符 [‘a’..’z’] ,集合输入的形式为

一个以“回车符“为结束标志的字符串,串中字符顺序不限。

(2) 演示程序以用户和计算机的对话方式执行,即在计算机终端上显示“提

示信息“之后,由用户在键盘上输入演示程序中规定的运算命令﹔相应的输入数

据和运算结果显示在其后。 

1.3 程序执行的命令包括:

(1)构造集合1;

(2)构造集合2;

(3)求并集;

(4)求交集;

(5)求差集;

1.4 测试数据

(1)Set1="magazine",Set2="paper",

Set1∪Set2="aegimnprz",Setl ∩Set2="ae",Set1-Set2="gimnz"。

(2)Set1= " 012oper4a6tion89",Set2="error data",

Set1∪Set2="adeinoprt",Setl ∩Set2="aeort",Set1-Set2="inp"。

1.5 实现提示

以有序链表表示集合。

  • 数据结构的选择和概要设计

为实现上述程序功能,应该以有序链表表示集合,因此需要两个抽象数据类型:有序表和集合。

2.1 有序表的抽象数据类型定义为:

ADT OrderedList

{

数据对象:D={ai|ai CharSet,i=1,2,3,...n}

数据关系:R1={<ai-1,ai>|ai-1,ai  D,ai-1<ai,i=1,2,...n}

基本操作:

InitList(&L)

操作结果:构造一个空的有序表L。

DestroyList(&L)

初始条件:有序表L已经存在。

操作结果:销毁有序表L。

Length(L)

初始条件:有序表L已经存在。

操作结果:返回有序表L的长度。

ListEmpty(L)

初始条件:有序表L已经存在。

操作结果:若有序表L为空表,返回True,否则返回False。

GetElem(L,pos)

初始条件:有序表L已经存在。

操作结果:若pos Length(L),则返回表中第pos哥数据元素。

LocateElem(L,e,&q)

初始条件:有序表L已经存在。

操作结果:若有序表L存在元素e,则q指示L中第一个值为e的元素的位置,并返回函数值TRUE,否则q指示第一个大于e的元素的前驱的位置,并返回函数值FALSE。

Append(&L,e)

初始条件:有序表L已经存在。

操作结果:在有序表L的末尾插入元素e

InsertAfter(&L,q,e)

初始条件:有序表L已经存在,q指示L中一个元素。

操作结果:在有序表L中q指示的元素之后插入元素e。

bianli(q,visit())

初始条件:有序表L已经存在,q指示L中第一个元素。

操作结果:依次对L中q指示的元素开始的每个元素调用函数visit()。

}ADT OrderList

2.2 集合的抽象数据类型为:

ADT Set

{

数据对象:D={ai|ai为小写字母且互不相同,i,2,...n}

数据关系:R1={}

基本操作:

Createset(&T,Str)

初始条件:Str为字符串

操作结果:生成一个由Str中小写字母构成的集合T。

Destoryset(&T)

初始条件:集合T已经存在。

操作结果:销毁集合T的结构。

UnionSet(&T,S1,S2)

初始条件:集合S1和S2都存在。

操作结果:生成一个由S1和S2的差集构成的集合T。

Printset(T)

初始条件:集合T已经存在。

操作结果:按字母次序顺序显示集合T的全部元素。

}AND Set

2.3 程序组成

本程序包含四个模块:

  1. 结点结构单元模块——定义有序表的结点结构;

(2)有序表单元模块——实现有序表的抽象数据类型;

(3)集合单元模块——实现集合获得抽象数据类型;

(4)主程序模块

(5)int main(){

初始化;

构造集合 1;

构造集合 2;

if(接收命令){

处理命令

}退出

2.4 模块流程图

图2.1 系统模块流程图

图2.2 函数调用流程图

图2.3 主菜单流程图

图2.4 用户操作流程图

2.5 结构体设计

typedef struct SET{

char *elem;

int size;

int length;

}set;

  • 详细设计和编码

3.1 源代码

#include<iostream>

using namespace std;

#define OK 1

#define ERROR 0

typedef int Status;

typedef char ElemType;

//定义线性链表

typedef struct LNode

{

    ElemType data;

    struct LNode *next; 

}LNode, *LinkList;

//初始化操作

Status InitList(LinkList &L)

{

//构造一个空的单链表L

    L=new LNode;

    L->next=NULL;

    return OK;

}

//存储输入的字符串

Status cun_chu(ElemType *ch,int &length)

{

    length=0;

    ch[length]=getchar();

    length=1;

    ch[1000];

    while(true)

    {

       ch[length++]=getchar();

       if(ch[length -1 ]=='\n')

       {

           break;

       }

    }

    return OK;

}

//存储集合

Status Creat(LinkList &L)

{

    //初始化链表

    InitList(L);

    L = new LNode;

    L->next=NULL;

    LinkList r = L;

    int length;

    ElemType ch[1000];

    cun_chu(ch,length);

    for(int i=0;i<length;i++)

    {

       if(ch[i]<97 || ch[i]>122)

       {

           continue;

       }

       LinkList p = new LNode;

       p->data = ch[i];

       r->next = p;

       r=p;

     }

     r->next = NULL;

     return OK;

 }

//返回一个集合的长度

Status Length(LinkList L)

 {

    int i=0;

    while(L->next != NULL)    //下一个结点不为空

     {

        i++;

        L=L->next;

      }

      return i;

  }

 

//对一个字母集合进行从小到大的排序

Status Sort(LinkList &L)

{

    LinkList p,q,n;

    int l=Length(L);

    if(l<2)     //集合中只有一个元素

    {

       return OK;

    }

    int flag=1;     //控制集合是否需要重新遍历

    for(int i=l-1;i>0&&flag==1;i--)

    {

       flag=0;

       p=L;

       q=p->next;     //若从头结点开始,指向第一个有data值的结点

       n=q->next;     //指向与其相邻的下一个结点

       for(int j=0;j<i;j++)

       {

           if(q->data > n->data)    //遍历集合,只要存在前一个结点的data值大于后一个就交换两个节点的位置,并使flag的值为1

           {

              flag=1;

              p->next=n;

              q->next=n->next;

              n->next=q;

              q=p->next;

              n=q->next;

            }

            p=q;

            q=n;

            n=n->next;

        }

     }

     return OK;

 }

//输出集合

Status bianli(LinkList L)

 {

    if(L->next == NULL)

    {

       cout << "NULL";

     }

     else

     {

        LinkList p=L->next;

        while(p!=NULL)

        {

           cout<<p->data;

           p=p->next;

        }

     }

     cout<<endl;

     return OK;

  }

 

//创建并排序集合

Status CreatSet(LinkList &L)

{

    Creat(L);      //存储集合

    Sort(L);       //将集合中的元素从小到大排序

    return OK;

 }

//集合的并运算

Status UnionSet(LinkList A,LinkList B,LinkList &C)

{

    InitList(C);     //初始化集合C

    LinkList i = A->next;     //指向集合A的第一个元素

    LinkList j = B->next;     //指向集合B的第一个元素

    LinkList k = C;

    while(i!=NULL && j!=NULL)    //两个集合都没有遍历完

    {

       if(i->data < j->data)    //集合A的元素小于B

       {

           if(k->data != i->data)    //集合A的该元素与并集中的上一个存入的元素不同,执行存入

           {

              k->next=i;

              k=i;

           }

           i=i->next;

       }

       else if(i->data > j->data)    //集合A的元素大于B

       {

           if(k->data != j->data)    //集合A的该元素与并集中的上一个存入的元素不同,执行存入

           {

              k->next=i;

              k=j;

           }

           j=j->next;

       }

       else    //集合A的元素等于B

       {

           if(k->data != j->data)    //集合A的该元素与并集中的上一个存入的元素不同,执行存入

           {

              k->next=j;

              k=j;

           }

           i=i->next;

           j=j->next;

       }

    }

    if(j!=NULL)   //集合A已经遍历结束,集合B没有,将集合B中剩下所有元素插入,并且是不重复插入

    {

       int m;

       if(k->data != j->data)   //确保并集中不插入重复元素

       {

           k->next=j;

           m=1;

       }

       j=j->next;

       if(j!=NULL && m==1)

       {

           k=k->next;

           m=0;

       }

     }

     if(i!=NULL)   //集合B已经遍历结束,集合A没有,将集合A中剩下所有元素插入,并且是不重复插入

    {

       int n;

       if(k->data != i->data)   //确保并集中不插入重复元素

       {

           k->next=i;

           n=1;

       }

       i=i->next;

       if(i!=NULL)

       {

           k=k->next;

           n=0;

       }

     }

     if(k->next != NULL)

     {

        k=k->next;

     }

     k->next = NULL;

     return OK;

 }

 //集合的交运算

 Status InterSet(LinkList A, LinkList B, LinkList C)

 {

    InitList(C);

    LinkList i = A->next;     //指向集合A的第一个元素

    LinkList j = B->next;     //指向集合B的第一个元素

    LinkList k = C;

    while(i != NULL && j!=NULL)

    {

       if(i->data < j->data)

       {

           i=i->next;

        }

       else if(i->data > j->data)

       {

           j=j->next;

       }

       else

       {

           if(k->data != i->data)

           {

              k->next = i;

              k=i;

           }

           i=i->next;

           j=j->next;

        }

     }

     k->next = NULL;

     return OK;

  }

 

//集合的差运算

Status DifferentSet(LinkList A,LinkList B,LinkList C)

{

    InitList(C);

    LinkList i = A->next;     //指向集合A的第一个元素

    LinkList j = B->next;     //指向集合B的第一个元素

    LinkList k = C;

    while(i != NULL && j!=NULL)  //如果集合A的元素比B的小,说明该元素之后也不会出现在B集合

    {

       if(i->data < j->data)

       {

           if(k->data != i->data)

           {

              k->next=i;

              k=i;

           }

           i=i->next;

        }

       else if(i->data > j->data)

       {

           j=j->next;

       }

       else     //避免集合中重复元素的影响

       {

           int n=0;

           j=j->next;

           if(i->next ==NULL)

           {

              i=i->next;

           }

           while(i!=NULL && i->next != NULL)

           {

              if(i->data == i->next->data)

              {

                  i=i->next->next;

                  n=1;

              }

              else

              {

                  if(n==0)

                  {

                     i=i->next;

                  }

                  break;

              }

           }

        }

     }

     if(i)

     {

        k->next = i;    //如果A有剩余,直接加进去

     }

     else k->next =NULL;

     return OK;

 }

//菜单界面

Status showMenu()

{

    cout<<"***********"<<endl;

    cout<<"***1、集合的并运算***"<<endl;

    cout<<"***2、集合的交运算***"<<endl;

    cout<<"***3、集合的差运算***"<<endl;

    cout<<"***0、退出***"<<endl;

    cout<<"***********"<<endl;

    return OK;

 }

//主函数

Status main()

{

    showMenu();

    while(1)

    {

       int select;

       cout<<"请输入要执行的指令数字:"<<endl;

       cin>>select;

       switch(select)

       {

           case 1:     //集合的并集

              cout<<"**集合的并运算**"<<endl;

              LinkList A;

              cout<<"请输入集合A:"<<endl;

              CreatSet(A);

              //bianli(A);

              LinkList B;

              cout<<"请输入集合B:"<<endl;

              CreatSet(B);

              //bianli(B);

              LinkList C;

              UnionSet(A,B,C);

              cout<<"集合的并运算结果为:"<<endl;

              bianli(C);

              break;

           case 2:      //集合的交集

              cout<<"**集合的交运算**"<<endl;

              LinkList D;

              cout<<"请输入集合A:"<<endl;

              CreatSet(D);

              //bianli(D);

              LinkList E;

              cout<<"请输入集合B:"<<endl;

              CreatSet(E);

              //bianli(E);

              LinkList F;

              InterSet(D,E,F);

              cout<<"集合的交运算结果为:"<<endl;

              bianli(F);

              break;

           case 3:     //集合的差集

              cout<<"**集合的差运算**"<<endl;

              LinkList G;

              cout<<"请输入集合A:"<<endl;

              CreatSet(G);

              //bianli(G);

              LinkList H;

              cout<<"请输入集合B:"<<endl;

              CreatSet(H);

              //bianli(H);

              LinkList I;

              DifferentSet(G,H,I);

              cout<<"集合的差运算结果为:"<<endl;

              bianli(I);

              break;

              break;

           case 0:     //退出

              cout<<"欢迎下次使用"<<endl;

              system("pause");

              return OK;

              break;

           default:

              break;

       }

    }

    system("pause");

    return OK;

 }

  • 上机调试过程

4.1 调试示例

集合 1={magazine}

集合 2={paper}

4.2 调试结果

图片3.1  程序运行结果图

4.3 调试分析

(1)由于对集合的三种运算的算法推敲不足,在有序链表类型的早期版本未设置尾指针,导致算法低效。

(2)刚开始时忽略了一些变量参数的标识”&”,使调试程序时费时不少。今后应重视确定参数的变量和赋值属性的区分和标识。

  • 用户使用说明

程序运行后会显示菜单,用户可以根据菜单号输入相对应的数字,(如果用户输入1,程序将对两个集合进行并集运算并输出相应结果,用户输入2,程序将对两个集合进行交集运算对输出需要结果,用户输入3,程序将对两个集合进行差集运算并输出相应的结果,用户输入0,则程序运行结束,退出系统。)待用户输入相应的菜单号后,程序会提示用户输入集合A和集合B,用户输入完成后按下回车键,程序就会将两个集合的运算结果输出在屏幕上。只要用户不输入0,便可以一直进行运算,且每次可以输入不同的集合。

参考文献

[1]严蔚敏.吴伟民.数据结构 C 语言版.北京.清华大学出版社,2018.6.

[2]数据结构课程设计.https://www.docin.com/p-235288754.html

[3]数据结构课程设计——集合的并,交和差的运算.

[4]谭浩强.C语言程序设计.清华大学出版社

[5]严蔚敏.数据结构(C语言版).清华大学出版社,1999.

[6]严蔚敏.吴伟民.数据结构题集(C语言版).清华大学出版社,2003.5.

[7]李春葆.数据结构教程.清华大学出版社,2005.1.

[8]Jan Harrington(著).陈博(译).面向对象C++数据结构.科学出版社,2005.2.

[9]史蒂芬·普拉达.C Primer Plus 第6版 中文版【M】.人民邮电出版社,2019

[10]史蒂芬·普拉达.C++ Primer Plus中文版【M】.人民邮电出版社,2019

[11]数据结构课程设计-集合的并交和差运算(23页)-原创力文档


http://www.ppmy.cn/news/74387.html

相关文章

yolov8seg模型转onnx转ncnn

yolov8是yolo的最新版本&#xff0c;可做图像分类&#xff0c;目标检测&#xff0c;实例分割&#xff0c;姿态估计。 主页地址 这里测试一个分割模型。 模型如下 选yolov8n-seg模型&#xff0c;转成onnx&#xff0c;再转ncnn测试。 yolov8s-seg的ncnn版可以直接用这个 如果用…

【网络编程】实现UDP/TCP客户端、服务器

目录 一、UDP 1、Linux客户端、服务器 1.1udpServer.hpp 1.2udpServer.cc 1.3udpClient.hpp 1.4udpClient.cc 1.5onlineUser.hpp 2、Windows客户端 二、TCP 1、单进程版的TCP客户端、服务器 1.1tcpServer.hpp 1.2tcpServer.cc 1.3tcpClient.hpp 1.4tcpClient.cc …

【结构体Struct——简单使用】

文章目录 结构体定义结构体访问结构体成员结构体指针结构体作为函数参数结构体数组总结 结构体 在C中&#xff0c;struct是一种自定义的数据类型&#xff0c;用于将不同类型的变量组合在一起&#xff0c;形成一个逻辑上的实体。通过struct&#xff0c;我们可以在一个单独的实体…

数据存储应用与原理剖析

存储引擎 存储引擎就是存放和读取用户数据的地方&#xff0c;对于持久化的存储引擎而言&#xff0c;数据的归宿是非易失性的存储介质&#xff08;通俗意义上来说就是磁盘&#xff09;所以该以什么形式组织和存储数据&#xff0c;这就是存储引擎设计的艺术所在这一块涉及到和操…

iOS 小组件开发 iOS 小组件开发用到的技术

iOS 小组件开发 iOS小组件开发是指在iOS设备的主屏幕上添加自定义的小组件&#xff0c;用于显示特定的信息或提供简化的交互。iOS 14及更高版本引入了小组件功能&#xff0c;使用户能够在主屏幕上自定义并快速访问相关内容。 以下是iOS小组件开发的基本步骤&#xff1a; 设计小…

Mac电脑 Vscode : Flutter 开发环境搭建(最细节教程)

参考链接&#xff1a; MacVSCode安装flutter环境_mac vscode配置flutter_GalenWu的博客-CSDN博客 mac搭建Flutter环境以及初始化项目 - 简书 注意&#xff1a; *下载xcode 就包含git了, *苹果芯片和intel 芯片需要的环境不同&#xff0c;苹果芯片需要安装&#xff1a; Im…

Shell脚本基础应用

记录&#xff1a;427 场景&#xff1a;Shell脚本基础应用。脚本格式、执行方式、定义和使用变量、双引号和单引号、反引号和$()、读取用户输入和文件、输出与输入重定向、export命令、alias命令、exit命令、查看内建命令。 版本&#xff1a;CentOS Linux release 7.9.2009。 …

数字逻辑(计科专业)

数制、码制、逻辑运算 基本逻辑符号 半加器 用与非门实现 全加器 编码器 编码就是将信息装换成独特的代码或信号输出的电路 普通编码器&#xff1a;任何时候只允许输入一个有效编码信号&#xff0c;否则输出就会发生混乱。 优先编码器&#xff1a;允许同时输入两个以上的有效…