第一篇:约瑟夫环课程设计实验报告
《数据结构》
课程设计报告
课程名称:
课程设计题目:姓名: 院系: 专业: 年级: 学号: 指导教师: 《数据结构》课程设计
joseph环
计算机学院
2011年12月18日
目 录 课程设计的目的………………………………………………………………2 2 需求分析………………………………………………………………………2 3 课程设计报告内容……………………………………………………………3
1、概要设计……………………………………………………………………3
2、详细设计……………………………………………………………………3
3、调试分析……………………………………………………………………x
4、用户手册……………………………………………………………………x
5、测试结果……………………………………………………………………6
6、程序清单……………………………………………………………………7 4 小结 …………………………………………………………………………10
1、课程设计的目的
(1)熟练使用C++编写程序,解决实际问题;
(2)了解并掌握数据结构与算法的设计方法,具备初步的独立分析和设计能力;(3)初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能;(4)提高综合运用所学的理论知识和方法独立分析和解决问题的能力;
2、需求分析
1、问题描述:
编号是1,2,……,n的n个人按照顺时针方向围坐一圈,每个人只有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个仍开始顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。设计一个程序来求出出列顺序。
2、要求:
利用不带表头结点的单向循环链表存储结构模拟此过程,按照出列的顺序输出各个人的编号。
3、测试数据:
m的初值为20,n=7 ,7个人的密码依次为3,1,7,2,4,7,4,首先m=6,则正确的输出是什么?
输出形式:建立一个输出函数,将正确的输出序列
3、课程设计报告内容
概要设计:
在理解了题目后,我先想到的是我们所学的单链表,利用单链表先建立循环链表进行存贮,建立完循环链表后,我将所要编写的函数分为了两块,一块是经过学过的单链表改编的循环链表的基本操作函数,还有一块是运行约瑟夫环的函数。
详细设计:
我先建立一个结构体,与单链表一样,只是多了一个存密码的code域
struct LinkNode {
int data;
//顺序
int code;
//密码
LinkNode *next;
};建立一个类LinkList ,包含的函数:
LinkList();
//构造函数
void Creat(const int);
//创建循环链表
int Delete(LinkNode*);
//删除报到数的结点
int Joseph(int);
// 约瑟夫环 私有成员是
LinkNode* head;
//指向第一个结点的指针 LinkNode* elem;
// 同上
int len;
//长度
我定义了一个elem指针是为了约瑟夫环里运行方便,elem只在约瑟夫环这个函数里用到,其他函数没有特别大的用处。
构造函数与书上的没什么大差别,创建循环链表时,要考虑几个问题,一个是题目要求是不带头结点,所以head指针直接指向了第一个结点,我在创建链表时把第一个结点初始化data为1,表明这个结点是第一个结点。具体如下:
void LinkList::Creat(const int number)
//number为结点个数,也就是参与的人数 {
if(number==1)
//只有一个人的情况 {
head=elem=new LinkNode;
head->data=1;
cout<<“请输入密码:”< cin>>head->code; head->next=head;} else { head=elem=new LinkNode; head->data=1; cout<<“请依次输入各个密码:”< cin>>head->code;LinkNode*q=head; q=head; for(int i=1;i //将每个结点链接上,在链接时填入密码 { LinkNode*p=new LinkNode; p->data=i+1; cin>>p->code; q->next=p; q=p;} q->next=head; //构成循环链表 } len=number;} 在构建约瑟夫环的执行函数时,我首先考虑了递归调用的函数,原本的这个程序的所有的都定为elemtype类型的,虽然编译没出错,但是在连接时发生了错误,在老师的指导下改成了具体的int型。int LinkList::Joseph(int m){ if(len>1){ LinkNode *q;if(m==1) //在初始报数为1的情况下 { q=elem;int a=q->code; //将选中的结点的密码记录在a中 elem=elem->next;cout< //用已经删除的结点的存的密码作为下一次循环的报数值 } else //一般情况下 { for(int i=1;i elem=elem->next;//找到需要出列的结点 q=elem;elem=elem->next; //此处的elem指针指向要删除的结点的下一个结点,下 次递归调用时从这里开始向下循环报数 int a=q->code; cout< //在只有一个结点的情况下 cout< 最后还有一个Delete函数,在删除结点的时候要考虑几个特殊情况,头尾结点。删除第一个结点时,需要将head指针下移,尾结点的next也要指向第二个结点;删除尾结点时,要将尾结点前的结点与第一个结点相连。在设计这个函数时,我只考虑了当len大于1的情况,在只剩下一个结点时,不必要删除,直接输出data的值即可(在约瑟夫函数中有写)。具体函数如下: int LinkList::Delete(LinkNode *a) { if(len>1)//只考虑长度大于1的情况 { if(head==a){ int out=head->data;LinkNode* q=head; while(q->next!=head){ q=q->next;} q->next=head->next;head=head->next;delete a;len--; //用len记录删除后的循环链表的长度 return out;} else { LinkNode* q=head;int out=a->data; while(q->next!=a){ q=q->next;} if(a->next=head).//删除的是尾结点时(不知道为什么我写程序里总是编译出现错误) { q->next=head; //重新链接 delete a; len--; return out;} else { q->next=a->next; delete a; len--; return out; } } } } 5、测试结果: 程序清单: #include int data; int code; LinkNode *next;}; class LinkList { public: LinkList(); void Creat(const int); //~LinkList(); int Delete(LinkNode*); int Joseph(int); private: LinkNode* head; LinkNode* elem; int len; }; LinkList::LinkList() { head=elem=NULL; len=0;} void LinkList::Creat(const int number) { if(number==1){ head=elem=new LinkNode; head->data=1; cout<<“请输入密码:”< cin>>head->code; head->next=head;} else { head=elem=new LinkNode; head->data=1; cout<<“请依次输入各个密码:”< cin>>head->code; LinkNode*q=head; q=head; for(int i=1;i { LinkNode*p=new LinkNode; p->data=i+1; cin>>p->code; q->next=p; q=p; } q->next=head;} len=number;} int LinkList::Delete(LinkNode *a) { if(len>1) { if(head==a) { int out=head->data; LinkNode* q=head; while(q->next!=head) { q=q->next; } q->next=head->next; head=head->next; delete a; len--; return out; } else { LinkNode* q=head; int out=a->data; while(q->next!=a) { q=q->next; } q->next=a->next; delete a; len--; return out; } } } int LinkList::Joseph(int m){ if(len>1){ LinkNode *q; if(m==1) { q=elem; int a=q->code; elem=elem->next; cout< Joseph(a); } else { for(int i=1;i elem=elem->next; q=elem; elem=elem->next; int a=q->code; cout< Joseph(a); } } else cout< int main(){ int num,code; cout<<“请输入人数: ”; cin>>num; LinkList L; L.Creat(num); cout<<“请输入第一个上限数: ”; cin>>code; cout<<“出列顺序:”< L.Joseph(code); return 0;} 4、小结 一、这次课程设计的心得体会通过实践我的收获如下: 一开始接触数据结构课程设计真的挺难的,好多都不会,不是逻辑方面的问题,而是不具备动手能力,脑子里总有一团火,比如对于这个题目,一开始有很多的想法,想到了从逻辑上怎么实现他,要编写哪些程序,但是一到需要编写了就开始为难了,可以说是几乎不知道从哪里入手,参考了书本里的程序,仿照他的结构一步一步做下来,现在对于单链表的各种操作已经算是比较熟练了,让我知道光有理论知识还远远不够,需要多动手,写的多了自然就能手到擒来。 二、根据我在实习中遇到得问题,我将在以后的学习过程中注意以下几点: 1、认真上好专业实验课,多在实践中锻炼自己。 2、写程序的过程中要考虑周到,严密。 3、在做设计的时候要有信心,有耐心,切勿浮躁。 4、认真的学习课本知识,掌握课本中的知识点,并在此基础上学会灵活运用。 5、在课余时间里多写程序,熟练掌握在调试程序的过程中所遇到的常见错误,以便能节省调试程序的时间。 #include typedef struct LNode { //数据域 int cipher; //密码 int number; //编号 struct LNode *next; //指针域 }LNode,*LinkList; void InitList(LinkList &L) //创建一个只有头结点链表 { L =(LinkList)malloc(sizeof(LNode));if(!L){ exit(1); printf(“/n/nError!/n/n”);} L->next = L;} void CreateList(int n,LinkList &L)//初始化循环单链表 { LinkList p,q;q = L;printf(“分别输入每个人的密码:”);for(int i = 1;i <= n;i++){ int k; scanf(“%d”,&k); if(k <= 0) { printf(“nn密码有误!nn”); exit(1); } p =(LinkList)malloc(sizeof(LNode)); if(!p) { exit(1); printf(“/n/nError!/n/n”); } p->cipher = k; p->number = i; L->next = p; L = p;} L->next = q->next;free(q);} void PrintList(int x,int n,LinkList L)//输出出列顺序 { LinkList p,q;p = L;for(int i = 1;i <= n;i++){ for(int j = 1;j < x;j++) p = p->next; q = p->next; x = q->cipher; printf(“%d ”,q->number); p->next = q->next; free(q);} } int main(){ printf(“=============约瑟夫环==============nnn”); int n,x;LinkList L;L = NULL;InitList(L); //构造空链表 printf(“输入初始密码:”);scanf(“%d”,&x); //初始密码为x printf(“n”);printf(“输入参与总人数:”);scanf(“%d”,&n); //总共的人数n printf(“n”);CreateList(n,L); //建立好一个约瑟夫环 printf(“nnn===================================nn”); printf(“出列编号为:”);PrintList(x,n,L); //输出出列顺序 printf(“nn”);return 0;} 实习报告 题目:约瑟夫环 班级:08052712学号: 08052211姓名: 葛俊峰 一、需求分析 1.本演示程序中,编号为1,2,„,n的n个人按顺时针方向围坐一圈,每个人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,如此下去,直到所有人全部出列为止。 2.演示程序以用户和计算机的对话方式执行,即在计算机终端上显示“提示信息”之后,由用户在键盘上输入相应数据(即总人数,m的值,每个人所持的密码),运算结果显示在其后。 3.程序执行的命令包括: (1)构造链表;(2)输入数据;(3)执行报数,储存出列人的序号,删除出列人的信息以及把出列人的密码赋给m;(4)结束。 4.测试数据: m的初始值为20;n=7,7个人的密码依次为:3,1,7,2,4,8,4,首先m值为6,则这正确的出列顺序为6,1,4,7,2,3,5。 二、概要设计 为了实现上述操作,应以单向循环链表为存储结构。为此,需要1个抽象数据类型:线性表。 1.线性表的抽象数据类型为: ADT List{ 数据对象:D={ai|ai∈ElemSet,i=1,2,„,n,n≥0} 数据关系:R1={ 基本操作: InitList(&L) 操作结果:构造一个空的线性表L。 }ADT List 2.本程序包括三个模块: 1)主程序模块: void main(){ 初始化; 输入数据; 函数调用; } 2)构造链表并输入每个人信息的模块-----实现线性表的抽象数据类型; 3)运行模块-----模拟约瑟夫环依次出列; 各模块之间调用关系如下: 主程序模块 ↓ 构造链表并输入每个人信息的模块 ↓ 运行模块 三、详细设计 1.结点类型和指针类型 typedef struct Node{ int num; int password; struct Node *next; }LNode,*LinkList;//结点类型,指针类型 Status MakeNode(LinkList &p,Elem Type e) { //分配由p指向的数据元素为e、后继为“空”的特点,并返回TRUE,//若分配失败,则返回FALSE P=(LinkType)malloc(sizeof(NodeType)); If(!p)return FALSE; p->data=e;p->next=null;return TRUE; } viod Free Node(Link Type &p) { //释放p所指结点 } 2.主函数和其他函数 int main() { //主函数 LinkList L = NULL; LinkList s ,r; int n,i,j,m;//初始化 printf(“请输入人数nn”); scanf(“%d”,&n); printf(“请输入mn”); scanf(“%d”,&m); printf(“请依次输入每个人的密码n”);//输入数据 CreatList(L,s,r,n);//创建链表run(L,n,m);//模拟约瑟夫环并输出 return 0; }//main void CreatList(LinkList &L,LinkList &s,LinkList &r,int n) { //创建链表 int i=1; s=(LNode*)malloc(sizeof(LNode));//分配空间 scanf(“%d”,&s->password);//输入密码 s->num = i;//序号为i if(L==NULL) L=s; else r->next=s; r=s;//为下次连接做准备 for(i=2;i<=n;i++) { s=(LNode*)malloc(sizeof(LNode));//分配空间 scanf(“%d”,&s->password); s->num = i; r->next=s;//连接到下个结点 r=s;//为下次连接做准备 } r->next = L;//闭合L = r; } // void CreatList void run(LinkList &L,int n,int m) { //模拟约瑟夫环并输出 LinkList s,r; int i,j; for(i = 0;i < n;i ++) { for(j = 1;j < m;j ++) L = L->next;//报数 s = L->next; r = s->next; printf(“%dn”,s->num);//输出序号 m = s->password; L->next = r; free(s);//删除结点 } }//run 3.函数的调用关系图反映了演示程序的层次结构: main ↓↓ CreatListrun ↓↓ Make NodeFree Node 四、调试分析 1.刚开始由于使用头结点,使得程序不符合要求。 2.在写程序时忽略了一些变量参数的标识“&”,使调试程序费时不少。今后应重视确定参数的变量和赋值属性的区分和标识。 3.本程序模块划分比较简单且容易看懂,但头指针赋空不太合理。 4.本实习作业采用数据抽象的设计方法,将程序划分为3个层次,使得设计时思路清晰,实现调试顺利 五、用户手册 1.本程序运行环境为DOS操作系统,执行文件为约瑟夫环.exe。 2. 进入演示程序后出现提示信息: “请输入人数n” 输入后,出现提示信息: “请输入m” 输入后,出现提示信息: “请依次输入每个人的密码” 输入后,显示相应的结果。 数据结构上机实验报告 02090401 12 雒文杰 题目:约瑟夫环问题 一.问题描述 设有n个人围做一圈,现从某个人开始报数,数到m的人出列,接着从出列的下一个人开始重新报数,数到m的人又出列,如此下去,直到所有人都出列为止。试设计确定他们的出列次序序列的程序。 二.基本要求 运用循环单链表解决约瑟夫环问题。 三.算法说明 本程序采用循环单链表的算法来解决约瑟夫环问题:建立一个循环单链表,按顺序查找指定结点,找到后删除,最后打印删除的编号序列。 四 .源程序清单 #include /* 人的序号, 密码*/ struct clist *next; /* 指向下一个节点的指针 */ };typedef struct clist cnode;typedef cnode *clink;clink createclist(int *array,int len) /* 建立循环链表 */ {clink head;clink before;clink new_node;int i;head=(clink)malloc(sizeof(cnode));if(!head)return NULL;head->data=array[0];head->order=1;head->next=NULL;before=head;for(i=1;i if(!new_node) return NULL; new_node->data=array[i]; new_node->order=i+1; new_node->next=NULL; before->next=new_node; before=new_node;} new_node->next=head;return head;} void main(){clink head,ptr;int find,j,i,a,list[n];printf(“Please input 'm'n”);for(i=0;i printf(“n”);} head=createclist(list,n);printf(“input first 's'n”);scanf(“%d”,&a);for(i=1;i head=head->next; ptr=head->next; head->next=ptr->next; find=ptr->data; printf(“order is %dn”,ptr->order); free(ptr); /* 让最后一个人也出列 */ } } 计算机网络课程设计报告 姓名:王 齐 学号:1105010404 班级:计算机四班 指导老师:张会福 湖南科技大学计算机科学与工程学院 2014年02月 实验一: 一、设计题目 网络聊天程序的设计与实现 二、实验目的 1、加深对计算机网络通信系统工作原理的理解 通过编写计算机程序实现、模拟网络的某些功能,使自己理解并掌握计算机网络基本工作原理及过程。 2、提高网络编程和应用的能力 提高实际编程能力和灵活运用所学知识解决问题的能力。培养调查研究、查阅技术文献、资料、手册及编写技术文档的能力,理论运用于实践的能力。 三、课程设计要求 1、仔细分析每一个实验的具体内容、步骤和要求,按设计要求完成任务。 2、程序设计需要完成的程序流程图、说明文档和源程序清单。 3、提交课程设报告(包含课程设计名称、课程设计题目、课程设计内容、课程设计步骤、调试过程、课程设计结果以及结果分析、心得体会)、程序源文件、可执行文件。 四、程序原理 在计算机通信系统中,有两种通信方式:面向连接的TCP和面向报文的UDP。 TCP:传输控制协议。TCP提供可靠交付的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复、并且按序到达。所以服务器和客户端的通讯使用TCP来完成。确保服务器作为“中转站”能够得到、存储、转发正确的客户信息。 UDP:用户数据报协议。UDP用来支持那些需要在计算机之间传输数据的网络应用。包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。因为客户端之间的通讯(聊天)对数据正确性的要求不是太高,偶尔出错也不会有太大的影响。 本课程设计采用TCP方式来实现网络聊天程序。 五、课程设计步骤 1、TCP网络聊天程序 TCP传输控制提供可靠的,有保证的通信质量,是面向连接的通信。因此,在通信之前,通信双方就得采用建立连接。TCP通信采取C/S(客户机/服务器)模式。需要分别编写客户端程序和服务器端程序。 1)服务器端程序编写步骤: a)加载套接字库,创建套接字(WSAStartup()/socket()); b)绑定套接字到一个IP地址和一个端口上(bind()); c)将套接字设置为监听模式等待连接请求(listen()); d)请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept()); e)用返回的套接字和客户端进行通信(send()/recv()); f)返回,等待另一连接请求; g)关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。2)客户端程序编写步骤: a)加载套接字库,创建套接字(WSAStartup()/socket()); b)向服务器发出连接请求(connect()); c)和服务器端进行通信(send()/recv()); d)关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。 2、UDP网络聊天程序 与TCP不同,UDP在通信时并不要双方建立连接,它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。比如我们聊天用的ICQ和OICQ就是使用的UDP协议。因此,本设计同样采用UDP连接方式。 程序编写步骤: a)加载套接字库,创建套接字(WSAStartup()/socket()); b)绑定套接字到一个IP地址和一个端口上(bind()); c)发送和接收数据(sendto()/recvfrom()); d)关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。 六、程序流程图 TCP 七.实验总结(错误与解决方法) 1.必须先初始化Winsock DLL库,否则会显示错误代码: WSASYSNOTREADY 网络通信依赖的网络子系统还没有准备好。 WSAVERNOTSUPPORTED 所需的Windows Sockets API的版本未由特定的Windows Sockets实现提供。 2.窗口接收到数据包含“烫烫烫”,解决办法即用memset函数初始化数组: memset(sendBuf,0,sizeof(sendBuf));memset(recvBuf,0,sizeof(recvBuf)); 3.使用该程序时注意先打开服务器,再打开客户端,否则无法正确连接。 4.注意引入ws2_32.lib库文件。 实验二: 一.题目:PING程序的设计与实现 二.实验目的: PING程序是我们使用的比较多的用于测试网络连通性的程序。PING程序基于ICMP,使用ICMP的回送请求和回送应答来工作。由计算机网络课程知道,ICMP是基于IP的一个协议,ICMP包通过IP的封装之后传递。 三.实验原理: ping的原理: Ping命令的主要作用是检测网络上主机的状态。要是在几年前,我们还可以下如此断言,如果不能Ping通某台主机,那么也就无法Telnet或者FTP到这台主机,但随着互联网的安全意识的增加,出现了访问控制清单的路由器和防火墙,由于ICMP报文是在IP数据包中被传输的,而到达一台主机不仅取决于IP层是否到达,还取决于使用何种协议和端口。 四.PING程序的实现过程 要实现ping程序,需要实现以下步骤: 1.创建协议类型为IPPROTO_ICMP的原始套接字,设置套接字属性。 2.创建并初始化ICMP封包。 3.调用sendto函数向远程主机发送ICMP请求。 4.调用recfrom函数接受ICMP响应 五.核心模块的流程图: 六.相关截图: 1.PING本机: 2.Ping局域网: 七:实验总结(错误与解决方案) 1.按照指导书上的代码输入并成功编译运行,在CDM命令提示窗口使用该EXE时,返回Request Timed Out “request time out”这提示除了对方可能装有防火墙或已关机以外,还有就是本机的IP不正确和网关设置错误。①、IP不正确: IP不正确主要是IP地址设置错误或IP地址冲突,这可以利用ipconfig /all这命令来检查。在WIN2000下IP冲突的情况很少发生,因为系统会自动检测在网络中是否有相同的IP地址并提醒你是否设置正确。在NT中不但会出现“request time out”这提示而且会出现“Hardware error”这提示信息比较特殊不要给它的提示所迷惑。 ②、网关设置错误:这个错误可能会在第四个步骤出现。网关设置错误主要是网关地址设置不正确或网关没有帮你转发数据,还有就是可能远程网关失效。这里主要是在你Ping外部网络地址时出错。错误表现为无法Ping外部主机返回信息“Request timeout”。 实验三: 一.实验题目: 基于IP多播的图形界面会议程序 二.实验目的 理解IP多播原理,并熟悉IP多播协议。 运用IP多播知识,设计一个图形界面的网络会议程序。 三.设计要求 1、理解IP多播原理,熟悉IP多播协议。 2、了解IP多播的编程步骤。 3、用VisualC++实现局域网IP多播。 四.设计原理 IP多播地址和多播组 IP多播通信必须依赖于IP多播地址,在IPv4中它是一个D类IP地址,范围从224.0.0.0到239.255.255.255,并被划分为局部链接多播地址、预留多播地址和管理权限多播地址三类。其中,局部链接多播地址范围在224.0.0.0~224.0.0.255,这是为路由协议和其它用途保留的地址,路由器并不转发属于此范围的IP包;预留多播地址为224.0.1.0~238.255.255.255,可用于全球范围(如Internet)或网络协议;管理权限多播地址为239.0.0.0~239.255.255.255,可供组织内部使用,类似于私有IP地址,不能用于Internet,可限制多播范围。 使用同一个IP多播地址接收多播数据包的所有主机构成了一个主机组,也称为多播组。一个多播组的成员是随时变动的,一台主机可以随时加入或离开多播组,多播组成员的数目和所在的地理位置也不受限制,一台主机也可以属于几个多播组。此外,不属于某一个多播组的主机也可以向该多播组发送数据包。 五.设计步骤 接收功能实现步骤: (1)、创建一个SOCK_DGRAM类型的Socket。 (2)、将此Socket绑定到本地的一个端口上,为了接收服务器端发送的多播数据。(3)、加入多播组。(4)、接收多播数据。 发送功能实现步骤: (1)、创建一个SOCK_DGRAM类型的Socket。(2)、加入多播组。(3)、发送多播数据。 多线程相关代码: InitSocket();RECVPARAM *pRecvParam=new RECVPARAM;pRecvParam->sock=m_socket;pRecvParam->hwnd=m_hWnd;//创建接收线程 HANDLE hThread=CreateThread(NULL,0,RecvProc,(LPVOID)pRecvParam,0,NULL);//关闭该接收句柄,释放其引用计数 CloseHandle(hThread); 程序截图: 六.实验总结(错误以及解决方案) 1.不能同时实现接收和发送功能:经查阅资料发现这是由于接收和发送功能的源代码中都有加入多播组程序段,一个程序不能多次加入同一个多播组。后来共同加入多播组程序段,不再让接收和发送功能分别运行加入多播组程序段。 2.当编辑框内当前显示内容满了之后,垂直滚动条不能自动下跳,需要手动拉下去,调用编辑框类的LineScroll函数和GetLineCount(); m_edit_recv.LineScroll(m_edit_recv.GetLineCount());第二篇:数据结构课程设计——约瑟夫环报告(含代码)
第三篇:数据结构报告--约瑟夫环范文
第四篇:题目:约瑟夫环问题
第五篇:计算机网络课程设计实验报告