约瑟夫环C++代码及实验报告
数据结构课程设计 约瑟夫环问题(报告+代码)

学院计算机与信息工程系数据结构课程设计设计题目:约瑟夫环问题专业班级学号姓名指导教师2010年12月20日约瑟夫环一.实验目的:本实验是设计一个可以解决约瑟夫环问题的程序。
此程序要求利用单向循环链表存储结构模拟此过程,按照出列的顺序印出个人的编号。
二.实验环境:VC2008.三.试验步骤:1.问题分析和任务定义本实验要求设计一个程序解决约瑟夫环问题,且要利用单向循环链表存储结构模拟此过程。
这就要求我们必须用链表结构而不能用像数组等其它结构。
首先输入的数据必须是整型且是整数,同样输出的也必须是整型且整数;其次也要备好测试数据(包括合法的输入数据和非法形式输入的数据)以此来检查程序是否符合要求;最后2.数据类型和系统设计链表存储结构的定义:typedef struct Node{}SeqList链表的建立:SeqList * Creat(int num){}链表的输出:void OutQueue(SeqList * tail, int num, int code){}3.详细设计:#include <stdio.h>#include <stdlib.h>typedef struct Node{int num;int code;struct Node * next;}SeqList;SeqList * Creat(int);void OutQueue(SeqList *, int , int );int main(){int n,m,i;printf( " 姓名:徐正杰学号:090502201:\n");printf("Input The Number of People, Frist Code:");{int num = 0,code = 0;scanf("%d%d",&num, &code);{SeqList * tail = NULL;tail=Creat(num);OutQueue(tail, num, code);}}return 0;}SeqList * Creat(int num){getchar();SeqList * tail = NULL;tail=(SeqList *)malloc(sizeof(SeqList));{int i = 1, code = 0;printf("Input Num.%d Code:", i);scanf("%d", &code);tail->num = i;tail->code = code;tail->next = tail;{SeqList * p = NULL;for(i = 2; i <= num; ++i){p = (SeqList *)malloc(sizeof(SeqList));if(p){printf("Input Num.%d Code:", i);scanf("%d", &code);p->num = i;p->code = code;p->next = tail->next;tail->next = p;tail = p;}else{perror("Out of menroy!");getchar();exit(1);}}}}return(tail);}void OutQueue(SeqList * tail, int num, int code) {printf("Out of Queue:");{SeqList * p;while(tail - tail->next){code=(code-1)%num+1;{int i;for(i = 1; i < code; ++i){tail = tail->next;}}p = tail->next;printf("%d,", p->num);tail->next = p->next;code = p->code;free(p);p = NULL;--num;}}printf("%d.",tail->num);free(tail);tail = NULL;}4.调试分析在本次试验调试中很不顺利。
c语言经典例题古老问题的解决

c语言经典例题古老问题的解决以下是一个经典的C语言例题,它是关于解决一个古老的问题:约瑟夫环问题。
约瑟夫环问题是一个著名的数学和计算机科学问题,其描述如下:有n个人围成一圈,从第k个人开始报数,数到m的人出圈,然后从下一个人开始重新报数,数到m的人再出圈,直到剩下最后一个人。
求最后留下的人在原序列中的编号。
以下是一个使用C语言解决这个问题的示例代码:```cinclude <>include <>int main() {int n, k, m;printf("请输入人数n:");scanf("%d", &n);printf("请输入开始报数的位置k:");scanf("%d", &k);printf("请输入数到m的人出圈的数m:");scanf("%d", &m);int a = (int )malloc(n sizeof(int));for (int i = 0; i < n; i++) {a[i] = i + 1;}int index = k - 1; // 初始位置为第k个人while (n > 1) {for (int i = 0; i < n; i++) {index = (index + m - 1) % n; // 计算下一个要出圈的人的位置printf("出圈的人是:%d\n", a[index]);free(a[index]); // 释放该位置的内存n--; // 人数减1}if (index >= k) { // 如果最后一个出圈的人的位置大于等于k,则交换位置,保证下次从第k个人开始报数int temp = a[index];a[index] = a[0];a[0] = temp;}index = (index + 1) % n; // 重新开始报数}printf("最后留下的人是:%d\n", a[0]); // 最后留下的人即为所求结果 free(a); // 释放整个数组的内存return 0;}```该程序首先要求用户输入人数n、开始报数的位置k和数到m的人出圈的数m,然后创建一个长度为n的数组a,将数组中的元素初始化为1到n 的整数。
数据结构实验报告(约瑟夫环)

基础成绩:82分《数据结构》课程实验实验报告题目:Joseph问题求解算法的设计与实现专业:网络工程班级:网络102姓名:***学号: ******完成日期:2012/6/20一、试验内容-约瑟夫(Joseph)问题的一种描述是:编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。
开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。
报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。
试设计一个程序求出出列顺序。
二、试验目的掌握链表的基本操作:插入、删除、查找等运算,能够灵活应用链表这种数据结构。
三、流程图struct list{-int num,code;struct list *next;};void main(){printf("Joseph问题求解算法的设计与实现\n \n");int i,j,m=1;int key; // 密码.int n; //人数.list *p,*s,*head;head=(list *)malloc(sizeof(list)); //为头结点分配空间.p=head; //使指针指向头节点printf("输入人的总个数:");scanf("%d",&n);for(i=1;i<=n;i++){printf("第%d个人的密码:\n",i);scanf("%d",&key);s=p;p=(list *)malloc(sizeof(list)); //创建新的结点.s->next=p;p->num=i;p->code=key;}p->next=head->next;p=head;head=head->next;free(p); //释放头结点.p=head;printf("\n\n输入初始值:\n");scanf("%d",&key);printf("\n出列顺序为:\n");do{ j=1; p=head;while(j<key){s=p;p=p->next;//使P指向下一结点j++;} //报数过程.i=p->num;key=p->code;printf("%d\n",i);s->next=p->next;-head=p->next; //重新定义head,下次循环的开始结点.free(p);// 释放已出列的结点.n--; //人数减一.}while(n>0);int x;printf(“输入0退出:”);scanf(“%d”,&x);for(;;){if(x==o)break;}}五、调试过程调试过程中,曾出现过缺少分号、括号之类的错误,还出现过运算顺序颠倒,致使运算出现了错误,在经过仔细的检查并且向人请教,终于得出了正确结果.六、结果分析输入人数:7 输入密码:3 1 7 2 4 8 4 初值:6排序结果:6 1 4 7 2 3 5。
C++版约瑟夫环

实验三约瑟夫环实验
1 约瑟夫环操作验证
1.1 实验内容
约瑟夫环问题,设有编号为1,2,3......,n的n个人围成圈,每个人持有一个密码m,从第一个人开始报数,报道m时停止报数,报m的人出圈,再从他的下一个人起重新报数,报到m时停止报数,报m 的出圈,直到所有人全部出圈为止。
当任意给定n和m后,求n个人的出圈次序
1.2 实验过程错误分析
(1)标调符号错误
语句后面缺少“;”,经常犯这种常识性错误。
(2)类定义错误
在头文件中对于Creatysf的定义为void Creatysf,而在函数的声明中,
我缺少了void对其定义,导致程序不符合。
应该要根据头文件的类型对以下的函数进行一对一的对应。
(3)主函数错误
错误在于ysf Jos(n,m),因为Jos(n,m)对应Creatysf,所以,应该改为
ysf Jos;
Jos.Creatysf(n,m);
1.3 知识点归纳
(1)解决本题的方法采用循环链表的形式解决的,让我们将单链表问题与实际生活问题联系,更好地学会运用所学的知识。
编程是通过计算机来解决问题,使生活更方便化。
(2)通过约瑟夫环的学习,我觉得在做数据结构编程时,需要先建立一种数学模型,这样才可以更有条理地去解决问题。
(3)循环链表的建立,需要考虑指针的问题,指针是代表一种地址,之前对于指针的概念我也是有点混淆,通过这次的实验,我领悟了一
些之前不懂的。
(4)在现在学习数据结构中,感觉只是有些不足,之前没有学好C++,导致现在有些缺漏,所以需要在多加把劲。
1.4 完整实验代码
Ysf.h文件
ysf.cpp
主函数
调试结果。
实验报告1约瑟夫环

《数据结构》实验报告班级:姓名:学号:日期:08-10-20题目:约瑟夫环一、上机实验的问题和要求:问题描述:编号为1到n的n个人围成一圈,每人带一个密码c,以m为报数上限。
然后从第一个人开始顺时针自1开始报数,报到m的人出列,将其密码作为新的m值,从他的下一个人开始,同样顺时针自1开始报数,依次循环下去,直到所有的人都出列!要求得到依次出列的那些人的编号序列!基本要求:用C代码实现此活动,要求使用一定的算法进行操作,并最终通过程序运算出最后的结果!二、程序设计的基本思想,原理和算法描述:(包括程序的模块结构,数据结构,输入/输出设计,符号名说明等)基本思想:利用不带头结点单向循环链表模拟该活动,在实现了一切动作之后,运用一定的算法得到最终的结果。
程序的模块结构:定义了相关的结构体之后,主要有以下几大模块:1.建立由头指针指示的有n个结点的不带头结点的单向循环链表crt_CLinkList(H,n);2.寻找、输出、删除H单循环链表的第m个结点locfor(H,m);3.最后通过main函数体处理参数的输入与显示,并调用以上两函数,最终解决问题。
主要数据结构:单链的循环链表,即线性表的链式存储结构。
算法的伪码描述:结构体定义如下:typedef struct Lnode /*定义单链表*/{int number; /*编号*/int cipher; /*密码*/struct Lnode *next; /*指针*/}Lnode,*CLinklist; /*重定向命名*/CLinklist H; /*H为全局单链表*/算法的实现详见源程序。
输入/输出设计本程序并未采用任何二进制文件出入的方式,这点说明将在最后总结提到。
至于函数的出入口问题,在源程序及注释中将得到详细说明,这里不再赘述。
三、源程序及注释:(说明函数功能、入口及出口参数,其他)#include <stdio.h> /* 头文件*/#include <stdlib.h>#include <alloc.h>typedef struct Lnode /*定义单链表*/{int number; /*编号*/int cipher; /*密码*/struct Lnode *next; /*指针*/}Lnode,*CLinklist; /*重定向命名*/CLinklist H; /*H为全局单链表*/struct Lnode *crt_CLinkList(CLinklist H,int m) /*创建一个不带头结点的单向循环链表*/{ /*其中,H为全局单链表,m为链表结点总数*/ int i; /*循环记数用*/struct Lnode *ptr1; /*用于索引*/if((ptr1=(struct Lnode *)malloc(sizeof(struct Lnode)))==NULL) /*一旦动态内存分配失败,报错退出!*/ {perror("malloc");return ptr1;}H=ptr1; /*形成单个结点的单循环链表*/ptr1->next=H;for(i=1;i<m;i++) /*形成m个结点的不带头结点的单循环链表*/ {if((ptr1->next=(struct Lnode *)malloc(sizeof(struct Lnode)))==NULL){perror("malloc");ptr1->next=H;return H;}ptr1=ptr1->next; /*其中H指头,ptr指尾*/ptr1->next=H;}return H; /*返回成功新建的单链表H*/}void locfor(CLinklist H,int m) /*寻找输出删除链表H中的第m个结点*/{ /*H为全局链表,m为要查找删除的结点位置*/ int i; /*循环计数*/struct Lnode *ptr;for(i=1;i<=5;i++) /*考虑图形界面的美观问题*/printf("number\tcipher\t");i=1; /*初始化*/while(H->next!=H) /*只剩单个结点时停止循环,进行最后输出!*/ {if(m==1) /*考虑进行自身删除的情况,即m=1*/{for(ptr=H->next;ptr->next!=H;ptr=ptr->next);/*正因为是自身删除才要费大劲寻找其父结点*/printf("%-6d\t",H->number); /*找到后,先输出*/printf("%-6d\t",H->cipher);m=H->cipher; /*确定下一次寻找的m值*/ptr->next=H->next; *删除结点,即自身结点*/ptr=ptr->next;free(H); /*因为对于链表中的结点,每个之前都分配了内存,所以free是必要的*/H=ptr; /*不同于以下普通结点的删除,自身删除还要还原H*/i=1; /*i重置,以方便下一次的循环操作*/}else if(i==m-1) /*因为从自身开始即为1号,因为m-1,而不是m*/{ptr=H->next; /*结点的删除操作同于上面的情况!*/printf("%-6d\t",ptr->number);printf("%-6d\t",ptr->cipher);m=ptr->cipher;H->next=ptr->next;H=H->next;free(ptr);i=1;}else{H=H->next; /*若未找到,则继续遍历!*/i++;}}printf("%-6d\t",H->number); /*对于单个结点的单循环链表,进行最终的输出操作!*/ printf("%-6d",H->cipher);free(H); /*完成所有任务并释放所有内存占用!*/}void main() /*主函数接口*/{ /*调用所有函数,进行实验模拟,并得出实验结果!*/ int i,j,n=30,m,k;struct Lnode *ptr;randomize(); /*因为下面调用了random函数,故此处的初始化很有必要!*/ printf("Now the experiment will begin.You have two choices!\n");/*数据输入可以电脑随机,也可以自行输入*/printf("If you want to enter the datas all by yourself,please enter 1.\n");/*自行输入(方便检测程序问题)*/ printf("If you want to get the datas by the computer,please enter 0.\n"); /*电脑随机产生数据*/printf("Now your choice:"); /*用户选择*/scanf("%d",&j);while(j!=0&&j!=1) /*考虑程序的完善性,对于误输入的提示并报警!*/ {printf("\nYou enter is unillage!Please try again!\n");printf("Now your choice:"); /*重新输入*/scanf("%d",&j);}H=crt_CLinkList(H,n); /*初始化链表*/if(j==0) /*电脑随机充入数据*/for(i=1;i<=30;i++){H->number=i;H->cipher=rand(); /*随机函数*/H=H->next;}else /*此时选择实验者输入数据!*/{for(i=1;i<=30;i++){H->number=i;printf("Now number %d,please enter the cipher:",i);scanf("%d",&k);H->cipher=k;H=H->next;}}m=rand(); /*默认情况下,m随机产生*/printf("Do you want to enter the number m?Enter 1 to set or others cancel!\n");/*当然,如果想自已输,可以进行覆盖*/scanf("%d",&k);if(k==1) /*自行输入m值*/{printf("Please enter the number m:");scanf("%d",&m);}system("cls"); /*考虑屏幕大小,进行分屏显示*/printf("All followed are your datas!\n"); /*界面友善*/for(i=1;i<=5;i++)printf("number\tcipher\t");for(i=0;i<30;i++) /*显示所有处理前数据*/{printf("%-6d\t",H->number);printf("%-6d\t",H->cipher);H=H->next;}printf("And the number m is :%d\n",m);printf("\nAfter the program,the result is:\n");locfor(H,m); /*对所有数据进行实验处理,直至所有结点处理完!*/ getchar();printf("\nPress any key return!"); /*TC环境下,方便查看结果!*/getchar();}四、用户使用说明与测试运行结果:1.运行程序后,首先弹出界面,截图如右:理性化的选择:如果打1,则所有的cipher均由用户输入,这样方便对特殊数据进行程序测试!如果打0,那么所有的数据均由电脑产生!那如果打其他的呢?考虑到误输入,加了一个循环,以提高程序的健壮性!2.首先自行输入数据进行测试。
C++编写的 约瑟夫环问题 代码

程序源代码:#include <stdio.h>#include <malloc.h>#include<conio.h>#include <stdlib.h>#include<ctime>#define NULL 0typedef struct Node{int m;//密码int n;//序号struct Node *next;}Node,*Linklist;Linklist create(int z) //生成循环单链表并返回,z为总人数{int i,mm;Linklist H,r,s;H=NULL;printf("请按顺序依次为每个人添加密码:");for(i=1;i<=z;i++){printf("\ninput cipher=");scanf("%d",&mm);s=(Linklist)malloc(sizeof(Node));s->n=i;s->m=mm;printf("%d号的密码%d",i,s->m);if(H==NULL)//从链表的第一个节点插入{H=s;r=H;}else//链表的其余节点插入{r->next=s;r=s;//r后移}//for结束r->next=H;/*生成循环单链表*/return H;}void search(Linklist H,int m0,int z)//用循环链表实现报数问题{int count=1;//count为累计报数人数计数器int num=0;//num为标记出列人数计数器Linklist pre,p;p=H;printf("出列的顺序为:");while(num<z){do{count++;pre=p;p=p->next;}while(count<m0);{pre->next=p->next;printf("%d ",p->n);m0=p->m;free(p);p=pre->next;count=1;num++;}//while结束}void clean(){int system(const char *string);int inquiry;printf("请问需要清除上一次操作记录吗(1.清屏/2.不清屏)...?\n"); scanf("%d",&inquiry);if(inquiry ==1)system("cls");}void text(){int m0,z,i, choose,k=1; //k用来阻止第一次进入程序清屏操作Linklist H;bool chooseFlag=false;while(1){if(k!=1)clean();k++;while(!chooseFlag){printf(" ……………………欢迎进入约瑟夫环问题系统…………………… \n"); printf( "* 1.输入约瑟夫环数据 * \n"); printf(" * 2.什么是约瑟夫环 * \n"); printf(" * 3.退出系统 * \n"); printf("........................................................ \n"); printf("请输入相应的数字进行选择: ");scanf("%d",&choose);for(i=1;i<=4;i++){if(choose==i) { chooseFlag=true; break;}else chooseFlag=false;}if(!chooseFlag) printf("Error Input!\n");} //end while(!chooseFlag)if(choose==1) //if 开始{printf("Input how many people in it:");//z为总人数scanf("%d",&z);if(z<=30){H=create(z);//函数调用printf("\nInput the start code m0=");scanf("%d",&m0);search(H,m0,z);printf("\n\n\n");}else{printf("超过最大输入人数\n");break;}}else if(choose==2){printf("\n约瑟夫环问题:设有n个人,其编号分别为1,2,3,…,n,安装编号顺序顺时针围坐一圈。
数据结构:约瑟夫环实验报告

数据结构实验报告题目:约瑟夫环姓名:学号:专业班级:指导教师:课题工作时间:一.需求分析1.约瑟夫环(Joseph)问题的一种描述是:设有编号1,2,3。
n(n>0)的N个人围成一个圈,每个人持有一个密码(正整数)。
开始时从第k(1<=k<=n)个人按顺时针方向自1开始顺序报数,报到m(m为第K个人的密码)的人出圈,再以这个人顺时针方向上的下一个人的密码为m,并开始重新从1报数。
如此下去,直至所有人全部出列为止。
试设计一个程序求出出列顺序。
2.演示程序以用户和计算机的对话方式执行,即在计算机终端上显示“提示信息”之后,有用户在键盘上输入演示程序中规定的运算命令,相应的输入数据和运算结果显示在其后。
3.测试数据(1)m=20, n=7, 结果依次为为3,1,7,2,4,8,4(2)m=20,n=1(3)m=20,n=0前面一组为常规数据,后面两组为边缘数据二、概要设计本程序是多文件程序,构成的函数有int main() 主函数,输出出队序列int initsuiji() 随机数产生初始化int suiji(int x,int y) 随机数产生函数int InitList(SqList &L) 初始化顺序表int ListInsert(SqList &L,int i,ElemType e) 在顺序表中插入元素int ListDelete(SqList &L,int i,ElemType &e) 删除顺序表中的元素int shunxu(int number) 顺序存储算法JosephuNode *Creat_Node(int numbers) 创建单循环链表void Josephu(JosephuNode *head,int Password) 添加元素信息int lianbiao(int number) 链表算法其中,void main()是最主要的函数,分别执行两种算法,并在执行的同时按照出列顺序输出元素信息(编号,密码),并在结尾输出两种算法执行所用的时间长短。
数据结构约瑟夫环实验报告

《数据结构与算法设计》约瑟夫环实验报告——实验一专业:物联网工程班级:物联网1班学号:15180118姓名:刘沛航一、实验目的1、熟悉VC环境,学习使用C语言利用链表的存储结构解决实际的问题。
2、在编程、上机调试的过程中,加深对线性链表这种数据结构的基本概念理解。
3、锻炼较强的思维和动手能力和更加了解编程思想和编程技巧。
二、实验内容1、采用单向环表实现约瑟夫环。
请按以下要求编程实现:①从键盘输入整数m,通过create函数生成一个具有m个结点的单向环表。
环表中的结点编号依次为1,2,……,m。
②从键盘输入整数s(1<=s<=m)和n,从环表的第s个结点开始计数为1,当计数到第n个结点时,输出该第n结点对应的编号,将该结点从环表中消除,从输出结点的下一个结点开始重新计数到n,这样,不断进行计数,不断进行输出,直到输出了这个环表的全部结点为止。
例如,m=10,s=3,n=4。
则输出序列为:6,10,4,9,5,2,1,3,8,7。
三、程序设计1、概要设计为了解决约瑟夫环的问题,我们可以建立单向环表来存储每个人的信息(该人的编号以及其下一个人的编号),及结点,人后通过查找每个结点,完成相应的操作来解决约瑟夫问题。
(1) 抽象数据类型定义ADT Joh{数据对象:D={|,1,2,,,0}i i a a ElemSet i n n ∈=≥K数据关系:R1=11{,|,,1,2,,}i i i i a a a a D i n --<>∈=K基本操作:create(&J, n)操作结果:构造一个有n 个结点的单向环表J 。
show(J)初始条件:单向环表J 已存在。
操作结果:按顺序在屏幕上输出J 的数据元素。
calculate( J,s,n)初始条件:单向环表J 已存在,s>0,n>0,s<环表结点数。
操作结果:返回约瑟夫环的计算结果。
}ADT Joh(2)宏定义#define NULL 0#define OK 1#define ERROR -1(3)主程序流程(4)程序分为下述模块:1)主函数模块——执行输入调用其他的功能函数2)创建环表模块——创建单向环表3)计算处理模块——计算出要出列的标号并输出4)显示模块——输出建立好的环表调用关系如下:2、详细设计(1)数据类型设计typedef int ElemType; //元素类型typedef struct {ElemType data;struct Joh *next;}Joh, *LinkList,*p; //结点类型,指针类型(2)操作算法Status create(LinkList &J,int n){//创建一个有n个结点的单向环表if(n<=0)return ERROR; //n<0错误J=(LinkList)malloc(sizeof(J));J->data=1;J->next=J;//建立第一个结点for(int i=n;i>1;--i){p=(LinkList)malloc(sizeof(J));p->data=i;p->next=J->next;J->next=p;//插入到表头}return OK;}//createvoid show(LinkList J){//主要的操作函数//顺序输出环表J的结点p=J;printf("%d ",p->data);p=p->next;while(p!=J){ //循环终止条件printf("%d ",p->data);p=p->next;}}//showvoid calculate(LinkList J,int s,int n){p=J;Joh *head=p; //声明结点while(p->data!=s){p=p->next;head=p;}//寻找起始结点while(p->next!=p){ //终止条件for(int i=0;i<n-1;i++){head=p; //保存前置节点p=p->next;}printf("%d ",p->data);head->next=p->next; //删除已输出结点p=head->next;}if(n!=1)printf("%d\n",p->data);elseprintf("\n");}//calculate(3)主函数代码int main(){//主函数Joh *J;int m,s,n;printf("The num of node is:");scanf("%d",&m);create(J,m); //创建单向环表Jshow(J); //输出J的数据printf("\n");printf("The first node which you want is:");scanf("%d",&s);printf("The internal which you want is:");scanf("%d",&n);calculate(J,s,n); //计算并输出结果return 0;}//main四、程序调试分析1、细节决定成败,编程最需要的是严谨,如何的严谨都不过分,往往检查了半天发现错误发生在某个括号,分号,引号,或者数据类型上。
C++数据结构之约瑟夫环

2009级数据结构实验报告实验名称:实验线性表实现约瑟夫问题求解学生姓名:桂柯易班级:2009211120班内序号:07学号:09210580日期:2010年10月31日1.实验要求【实验目的】1.熟悉C++语言的基本编程方法,掌握集成编译环境的调试方法;2.学习指针、模板类、异常处理的使用;3.掌握线性表的操作实现方法;4.培养使用线性表解决实际问题的能力。
【实验内容】利用循环链表实现约瑟夫问题的求解。
约瑟夫问题如下:已知n个人(n>=1)围坐一圆桌周围,从1开始顺序编号。
从序号为1的人开始报数,顺时针数到m的那个人出列。
他的下一个人又从1开始报数,数到m 的那个人又出列。
依此规则重复下去,直到所有人全部出列。
请问最后一个出列的人的编号。
2.程序分析2.1 存储结构存储结构:循环链表2.2 关键算法分析【设计思想】首先,设计实现约瑟夫环问题的存储结构。
由于约瑟夫环本身具有循环性质,考虑采用循环链表,为了统一对表中任意节点的操作,循环链表不带头结点。
循环链表的结点定义为如下结构类型:struct Node{int number;Node *next;};其次,建立一个不带头结点的循环链表并由头指针first指示。
最后,设计约瑟夫环问题的算法。
【伪代码】1、工作指针first,r,s,p,q初始化2、输入人数(n)和报数(m)3、循环n次,用尾插法创建链表Node *q;for(int i=1;i<=n;i++){Node *p;p=new Node;p->number=i;p->next=NULL;if(i==1) L=q=p;else{q->next=p;q=q->next;}}q->next=L;if(L!=NULL){return(L);}4、输入报数的起始人号数k;5、Node *q = new Node;计数器初始化i=1;6、循环n次删除结点并报出位置(其中第一个人后移k个)当i<n时移动指针m-2次p=p->next;删除p结点的后一结点qq=p->next;p->next=q->next;*L = p->next;报出位置后Delete q;计数器i++;【复杂度】for(int i=1;i<=n;i++){Node *p;p=new Node;p->number=i;p->next=NULL;if(i==1) L=q=p;else{q->next=p;q=q->next;}时间复杂度:O(n)if(i==1) i+=LengthList(*L);Node *p;p=*L;int j=0;while(j<i-2) {p=p->next;j++;}q = p->next;p->next=p->next->next;*L = p->next;return(q);时间复杂度:O(n2)算法的空间复杂度:O(n2)2.3 其他程序源代码:#include<iostream>using namespace std;struct Node//循环节点的定义{int number;//编号Node *next;};Node *CreateList(Node *L,int &n,int &m);//建立约瑟夫环函数void Joseph(Node *L,int n,int m);//输出每次出列号数函数Node *DeleteList(Node **L,int i,Node *q);//寻找每次出列人的号数int LengthList(Node *L);//计算环上所有人数函数void main()//主函数{Node *L;L=NULL;//初始化尾指针int n, m;cout<<"请输入人数N:";cin>>n;//环的长度if(n<1){cout<<"请输入正整数!";}//人数异常处理else{cout<<"请输入所报数M:";cin>>m;if(m<1){cout<<"请输入正整数!";}//号数异常处理else{L=CreateList(L,n,m);//重新给尾指针赋值Joseph(L,n,m);}}system("pause");}Node *CreateList(Node *L,int &n,int &m)//建立一个约瑟夫环(尾插法){Node *q;for(int i=1;i<=n;i++){Node *p;p=new Node;p->number=i;p->next=NULL;if(i==1) L=q=p;//工作指针的初始化else{q->next=p;q=q->next;}}q->next=L;if(L!=NULL){return(L);}//返回尾指针else cout<<"尾指针异常!"<<endl;//尾指针异常处理}void Joseph(Node *L,int n,int m)//输出每次出列的人{int k;cout<<"请输入第一个报数人:";cin>>k;if(k<1||k>n){cout<<"请输入1-"<<n<<"之间的数"<<endl;} else{cout<<"\n出列顺序:\n";for(int i=1;i<n;i++){Node *q = new Node;if(i==1) q=DeleteList(&L,k+m-1,q);//第一个出列人的号数else q=DeleteList(&L,m,q);cout<<"号数:"<<q->number<<endl;delete q;//释放出列人的存储空间}cout<<"最后一个出列号数是:"<<L->number<<endl;;//输出最后出列人的号数}}Node *DeleteList(Node **L,int i,Node *q) //寻找每次出列的人{if(i==1) i+=LengthList(*L);//顺序依次出列情况的处理方式Node *p;p=*L;int j=0;while(j<i-2) {p=p->next;j++;}q = p->next;p->next=p->next->next;*L = p->next;return(q);}int LengthList(Node *L)//计算环上的人数{if(L){cout<<"尾指针错误!"<<endl;}//异常处理else{int i=1;Node *p=L->next;while(p!=L){i++;p=p->next;}return(i);}}3.程序运行结果1.测试主函数流程:2.测试条件:如上图所示,人数为20人,所报数为6,第一个报数的人是1号。
约瑟夫环问题源代码(C语言)

约瑟夫环问题如下:已知n个人(n>=1)围桌一园桌周围,从1开始顺序编号。
从序号为1的人开始报数,顺时针数到m的那个人出列。
他的下一个人又从1开始报数,数到m的那个人又出列。
依此规则重复下去,直到所有人全部出列。
求解最后一个出列的人的编号。
本次实验是以顺序表求解约瑟夫环问题,程序流程图及程序运行结果如下:输入人数、所报数、第一个报数人编号存储并建立一个约瑟夫环通过循环结构依次查找每次出列的人的编号并输出输出最后一个出列的人的编号程序代码如下:#include<iostream>#include<process.h>#include<stdlib.h>using namespace std;struct Node //循环节点的定义{int number; //编号Node *next;};Node *CreateList(Node *L,int &n,int &m); //建立约瑟夫环函数void Joseph(Node *L,int n,int m); //输出每次出列号数函数Node *DeleteList(Node **L,int i,Node *q); //寻找每次出列人的号数int LengthList(Node *L); //计算环上所有人数函数void main() //主函数{system("color 75"); //设置颜色以美观Node *L;L=NULL; //初始化尾指针int n, m;cout<<"请输入人数N:";cin>>n; //环的长度if(n<1){cout<<"请输入正整数!";} //人数异常处理else{cout<<"请输入所报数M:";cin>>m;if(m<1){cout<<"请输入正整数!";} //号数异常处理else{L=CreateList(L,n,m); //重新给尾指针赋值Joseph(L,n,m);}}system("pause");}Node *CreateList(Node *L,int &n,int &m) //建立一个约瑟夫环(尾插法){Node *q;for(int i=1;i<=n;i++){Node *p;p=new Node;p->number=i;p->next=NULL;if(i==1) L=q=p; //工作指针的初始化 else{q->next=p;q=q->next;}}q->next=L;if(L!=NULL){return(L);} //返回尾指针else cout<<"尾指针异常!"<<endl; //尾指针异常处理}void Joseph(Node *L,int n,int m) //输出每次出列的人{int k;cout<<"请输入第一个报数人:";cin>>k;if(k<1||k>n){cout<<"请输入1-"<<n<<"之间的数"<<endl;}else{cout<<"\n出列顺序:\n";for(int i=1;i<n;i++){Node *q = new Node;if(i==1) q=DeleteList(&L,k+m-1,q); //第一个出列人的号数else q=DeleteList(&L,m,q);cout<<"号数:"<<q->number<<endl;delete q; //释放出列人的存储空间}cout<<"最后一个出列号数是:"<<L->number<<endl; //输出最后出列人的号数}}Node *DeleteList(Node **L,int i,Node *q) //寻找每次出列的人{if(i==1) i+=LengthList(*L); //顺序依次出列情况的处理方式Node *p;p=*L;int j=0;while(j<i-2) {p=p->next;j++;}q = p->next;p->next=p->next->next;*L = p->next;return(q);}int LengthList(Node *L) //计算环上的人数{if(L){cout<<"尾指针错误!"<<endl;} //异常处理else{int i=1;Node *p=L->next;while(p!=L){i++;p=p->next;}return(i);}}实验体会:通过对本问题的分析,我进一步熟悉了对各种逻辑表达式的判断和指针的使用。
约瑟夫环C 代码及实验报告

{
outArray[k]=listArray[j];// 将 该 元 素 放 置 到 出 列 数 组
里,并输出
cout<<outArray[k]<<" ";
k++;
listArray[j]=0; //将出列元素置 0
i=1; //下一个元素从 1 开始重新报数
}
else
i++; //报数编号与出列编号不同时,继续报数
if(a[i]==1) {
j=j+a[i]; if(j==m) {
j=0; a[i]=0; k++; cout<<i<<" "; }
} if(i==n)
i=0; }
}
七、实验心得 李孟琪:该实验利用数组实现线性表,算法简便,但产生很多不必要的消耗,下 一步可以尝试采用单链表,双链表实现该问题。 李春阳:通过利用链表编写约瑟夫环,进一步掌握了约瑟夫环的原理,加深了对 链表使用的理解 雷鹤:这次实验遇到的最大问题是拘泥于基本要求中的利用数组来实现线性表, 并用线性表来实现约瑟夫环问题,在尝试用链表实现后问题变得简单了些;在插 入元素这一步费不少时间,头尾节点的移动关系也需要理解
四、详细设计
程序代码:
#include <iostream>
using namespace std;
main()
{
int n,m,k,j;
//n 为总人数,m 为出列编号
cin>>n>>m;
int *listArray=new int[n]; //将 n 个人放在大小为 n 的数组中
约瑟夫环实验报告

程序结束输 出结果
源 程 序 及 注 释
#include<iostream> using namespace std; struct Node //记录乘客的信息 { Node * nextnum; int num; }; int main() { int n,m,l,retainer; cout<<"Input n,m,k:"<<endl; //输入 n、m、k 这三个数据 cin>>n>>m>>l; Node * former,* latter; former=latter=new Node; former->num=1; for(int i=1;i<n;i++) //开始构造链表 { Node *s=new Node; s->num=i+1; latter->nextnum=s; latter=s; } latter->nextnum=former; retainer=n; do { for(int data=1;data<m;data++){ //do while 循环语句来实行 latter=latter->nextnum; 指针的指向和修改 former=former->nextnum; } latter->nextnum=former->nextnum; delete former; former=latter->nextnum; retainer--; }while(retainer>l); cout<<"留下来的人的号码是:"<<endl; //输出结果, 找到被扔进大海里 for(int j=1;j<=l;j++) 的人 { cout<<former->num<<"\t"; former=former->nextnum; } return 0; }
约瑟夫环实验

约瑟夫问题一、流程图。
1.建立约瑟夫环;2.输出每次出列号数;3.寻找每次出列人;4.计算环上所有人数二、源代码。
#include<iostream>#include<conio.h>using namespace std;struct Node//循环节点的定义{int number;//编号Node *next;};Node *CreateList(Node *L,int &n,int &m);//建立约瑟夫环函数void Joseph(Node *L,int n,int m);//输出每次出列号数函数Node *DeleteList(Node **L,int i,Node *q);//寻找每次出列人的号数int LengthList(Node *L);//计算环上所有人数函数void main()//主函数{system("color 1d");Node *L;L=NULL;//初始化尾指针int n, m;cout<<"请输入人数N:";cin>>n;//环的长度if(n<1){cout<<"请输入正整数!";}//人数异常处理else{cout<<"请输入每隔几个人报一次数M:";cin>>m;if(m<1){cout<<"请输入正整数!";}//号数异常处理 else{L=CreateList(L,n,m);//重新给尾指针赋值Joseph(L,n,m);}}system("pause");}Node *CreateList(Node *L,int &n,int &m)//建立一个约瑟夫环(尾插法){Node *q;for(int i=1;i<=n;i++){Node *p;p=new Node;p->number=i;p->next=NULL;if(i==1) L=q=p;//工作指针的初始化else{q->next=p;q=q->next;}}q->next=L;if(L!=NULL){return(L);}//返回尾指针else cout<<"尾指针异常!"<<endl;//尾指针异常处理}void Joseph(Node *L,int n,int m)//输出每次出列的人{int k;cout<<"请输入第一个报数人:";cin>>k;if(k<1||k>n){cout<<"请输入1-"<<n<<"之间的数"<<endl;}else{cout<<"\n出列顺序:\n";for(int i=1;i<n;i++){Node *q = new Node;if(i==1){q=DeleteList(&L,k+m-1,q);}//第一个出列人的号数else{q=DeleteList(&L,m,q);}cout<<"号数:"<<q->number<<endl;delete q;//释放出列人的存储空间}cout<<"最后一个出列号数是:"<<L->number<<endl;;//输出最后出列人的号数}}Node *DeleteList(Node **L,int i,Node *q) //寻找每次出列的人{if(i==1) i+=LengthList(*L);//顺序依次出列情况的处理方式Node *p;p=*L;int j=0;while(j<i-2) {p=p->next;j++;}q = p->next;p->next=p->next->next;*L = p->next;return(q);}int LengthList(Node *L)//计算环上的人数{if(L){cout<<"尾指针错误!"<<endl;}//异常处理else{int i=1;Node *p=L->next;while(p!=L){i++;p=p->next;}return(i);}}三、运行结果。
约瑟夫环问题 c++实现 实验报告

HUNAN UNIVERSITY 课程实习报告题目约瑟夫环学生姓名学生学号专业班级指导老师完成日期2013.04.01一、需求分析1.本程序要求利用和链表,以实现经典的约瑟夫环问题。
两个正整数由用户通过键盘输入,其取值范围为(0,216)。
不对非法输入做处理,即假设输入都是合法的。
2.测试数据输入:10,3输出:3 6 9 2 7 1 8 5 10 43. 采用链表的形式来实现二、概要设计抽象数据类型为实现上述程序的功能,应以整数存储用户的输入,以及计算出的结果。
算法的基本思想利用链表和数组,约瑟夫环问题中的数据是人所在的位置,而这种数据是存在“第一元素、最后元素”,并且存在“唯一的前驱和后继的”,符合线性表的特点。
由于需要模拟约瑟夫环的出列问题,可以采用顺序表来实现线性表,完成出列顺序的输出。
核心算法主要分为两步:1、确定需要删除的位置,2、设置并删除该位置。
程序的流程程序由三个模块组成:(1)输入模块:完成个正整数的输入,存入变量n和m中。
(2)计算模块:利用数组和链表实现约瑟夫环(3)输出模块:屏幕上显示计算每次被踢出的人的位置三、详细设计物理数据类型1、用整形存储用户输入的整数。
2、用链表实现线性表算法的具体步骤约瑟夫环构建算法步骤:剔除过程算法步骤:算法的时空分析移除是循环赋值的时空代价是Θ(n)每次设置当前删除位置时都是向后一个查找,所以时空代价是Θ(1),又因为每次删除时做了n次定位,又有n次循环,所以总的时空代价是Θ(n2)。
输入和输出的格式Plesse enter the value of m 输入Plesse enter the value of n 输入输出五、测试结果输入10 3输出 3 6 9 2 7 1 8 5 10 4六、用户使用说明(可选)1、输入的n要大于m,并且要为整形七、实验心得(可选)这次实验是对以前内容的复习以及对新学知识的应用,在与同学讨论之后编出了代码,体会到了链表的作用,在参照书本之后先构造循环链表、再构造约瑟夫环、最终实现剔除过程,整个过程十分清晰,但本人对代码其还未掌握透彻,还需要更进一步努力。
约瑟夫环实验报告

class JosephCircle//定义JosephCircle类
{
public://定义成员函数
void input();
bool check();
void ruivate://定义成员变量
int totalNumber;
五、
1.使用了宏定义,在类初始化时定义了数组a[1000],造成内存大量浪费,降低了程序的效率;
2.类的封装不好,程序的可读性比较差;
3.注释描述不清。
六、
通过这次实验,对类和约瑟夫环的数组算法有了深刻的理解,对相关内容有了更熟练的掌握。由于对编程还不是很熟悉,实验过程中出现了很多错误,但调试过后大部分解决了。查阅资料,请教同学,分析问题,解决问题,提高了自己的动手能力。
int beginNumber;
int outNumber;
int a[max];
};
void JosephCircle::input()//输入人数、开始位置编号和第几个出列
{
cout<<"请输入人数: ";
cin>>totalNumber;
cout<<"请输入开始位置编号: ";
cin>>beginNumber;
return false;
}
return true;
}
void JosephCircle::run()//寻找合适的值
{
for(int j = 0; j < totalNumber; j++)//为数组赋值
{
a[j] = j + 1;
约瑟夫环实习报告(参考)

题目:编制一个程序模拟约瑟夫问题一﹑需求分析1. 本程序将模拟约瑟夫问题,求出出列的编号,并在每次出列后显示此时的顺序,本程序采用循环链表作为存储结构,无带头结点。
2. 输入可以是文件输入或标准输入,链表长度size>0,各个结点所带的密码值secret>0,第一次的报数m>0,若m<1,将提示更正。
3. 本程序在输入完毕后将先输出刚输入的内容,再提供报数后,开始进行运算,每出列一次将显示出列者和出列后链表顺序。
4. 测试数据:长度7,密码:3,1,7,2,4,8,4,报数初值6;长度-1,密码:3,2,5,6,4;长度5,密码:3,2,5,0,4; 长度5,密码:3,2,5,6,4,报数初值-1,4。
二﹑概要设计采用循环链表表示约瑟夫环1. 循环链表的抽象定义:ADT CycList{数据对象:D={i a ,i b |i a ,i b ∈ I ,i=1,2,…3,n>0}数据关系:R={<i a ,i b >|i a ,i b ∈D,I=1,2…3}基本操作:CreatList(&L,&in)初始条件:输入流有效,输入的值合法,申请空间成功操作结果:构造一个非空的循环链表PrintList(const L)初始条件:循环链表L 已存在操作结果:输出LFun(&L,Secret)初始条件:循环链表L 已存在操作结果:得到出列顺序}2. 本程序包含两个模块:1) 主程序模块2) 循环链表模块三﹑详细设计#include <iostream>using namespace std;//每个人的号码和密码。
struct people{int NO;int pass;}node;template <class Elem>class Link{private:static Link<Elem>* freelist;//静态数据成员的头接点。
约瑟夫环密码实验报告

一、实验目的1. 理解并掌握约瑟夫环问题的基本概念和解决方法。
2. 熟悉链表数据结构的操作和应用。
3. 利用C语言实现约瑟夫环问题的模拟,并输出出列顺序。
4. 提高编程能力和问题解决能力。
二、实验原理约瑟夫环问题是一种著名的数学问题,描述了n个人围成一圈,按照一定规则进行报数,当报到特定数字时,出列的人将被淘汰,然后重新开始报数,直到所有人都出列。
在本实验中,我们使用单向循环链表来模拟这个过程。
三、实验步骤1. 定义单向循环链表的数据结构,包括节点结构体和链表结构体。
2. 实现链表的基本操作,如创建链表、插入节点、删除节点等。
3. 编写模拟约瑟夫环问题的函数,包括初始化链表、报数、出列等操作。
4. 编写主函数,接收用户输入的参数,调用模拟函数,并输出出列顺序。
四、实验代码```c#include <stdio.h>#include <stdlib.h>// 定义节点结构体typedef struct Node {int number; // 编号int pass; // 密码struct Node next; // 指向下一个节点的指针} Node;// 创建单向循环链表Node createList(int n) {Node head = NULL, tail = NULL, newNode = NULL;for (int i = 1; i <= n; i++) {newNode = (Node)malloc(sizeof(Node));newNode->number = i;newNode->pass = rand() % 1000; // 随机生成密码 if (head == NULL) {head = newNode;tail = newNode;newNode->next = head;} else {tail->next = newNode;tail = newNode;tail->next = head;}}return head;}// 报数void count(Node head, int m) {Node current = head, pre = NULL;while (current->next != current) {for (int i = 1; i < m; i++) {pre = current;current = current->next;}printf("出列编号:%d,密码:%d\n", current->number, current->pass);pre->next = current->next;free(current);current = pre->next;}printf("最后出列编号:%d,密码:%d\n", current->number, current->pass);free(current);}// 主函数int main() {int n, m;printf("请输入人数n:");scanf("%d", &n);printf("请输入报数上限值m:");scanf("%d", &m);Node head = createList(n);count(head, m);return 0;}```五、实验结果与分析1. 运行程序后,输入人数n和报数上限值m,程序会自动生成一个单向循环链表,并按照约瑟夫环问题的规则进行模拟。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验一约瑟夫环问题实验报告
通信二班雷鹤20100820207
李春阳20100820208
李孟琪20100820209
一、问题描述
设编号为1-n的n(n>0)个人按顺时针方向围成一圈.首先第1个人从1开始顺时针报数.报m的人(m 为正整数).令其出列。
然后再从他的下一个人开始,重新从1顺时针报数,报m的人,再令其出列。
如此下去,直到圈中所有人出列为止。
求出列编号序列。
二、需求分析
1、需要基于线性表的基本操作来实现约瑟夫问题
2、需要利用数组来实现线性表
3、测试用例
输入:10,3
输出:3 6 9 2 7 1 8 5 10 4
三、概要设计
抽象数据类型
为实现上述程序的功能,应以整数存储用户的输入,以及计算出的结果。
算法的基本思想
利用数组来代表一个环,然后模拟报号出圈的过程,直到所有人都出圈。
程序的流程
程序由三个模块组成:
(1)输入模块:完成两个正整数的输入,存入变量n和m中。
(2)计算模块:计算这n个数的输出序列
(3)输出模块:屏幕上显示这n个数的输出序列。
四、详细设计
程序代码:
#include <iostream>
using namespace std;
main()
{
int n,m,k,j; //n为总人数,m为出列编号
cin>>n>>m;
int *listArray=new int[n]; //将n个人放在大小为n的数组中
int *outArray=new int[n]; //用以存放依此出列的人的编号
for(int i=0;i<n;i++)
listArray[i]=i+1; //对n个人进行编号
for(i=1,j=k=0;k<n;j=++j%n) //i为报数编号,初始值为1,循环访问数组元素,即数组元素循环报数
{
if(listArray[j]!=0)
{
if(i==m) //报数编号和出列编号相同时
{
outArray[k]=listArray[j];//将该元素放置到出列数组里,并输出
cout<<outArray[k]<<" ";
k++;
listArray[j]=0; //将出列元素置0
i=1; //下一个元素从1开始重新报数
}
else
i++; //报数编号与出列编号不同时,继续报数
}
}
cout<<'\n';
return 0;
}
物理数据类型
队列元素及出列序列都以整型数组方式存储
算法的具体步骤
(1)将队列里的元素编号
(2)循环访问数组元素
(3)第一个元素从1开始报数,报数编号与出列编号相同时出列,并将该元素置为0
(4)下一个元素重新从1开始报数,依次循环
输入和输出的格式
输入格式:n,m
输出格式1:在字符界面上输出这n个数的输出序列
输出格式2:将这n个数的输出序列写入到文件中
五、测试结果
其他程序代码
程序1
#include<stdio.h>
#include <stdlib.h>
typedef int type; //结点数据域类型为整型
typedef struct LNode //结点类型定义
{
struct LNode *next;//结点的指针域
type a; //结点的数据域
}link;
void initLink(link* &l)
{
l=(link*)malloc(sizeof(link));//在内存的动态存储区申请链表长度的连续空间
//初始化链表
l->next=l;
}
void insert(link* &l) //在其后插入新成员
{
link* p;
p=(link*)malloc(sizeof(link));
p->next=l->next;
l->next=p;
}
void destory(link* &l) //删除其后面的元素
{
link* t;
t=l->next;
l->next=l->next->next;
free(t);
}
int main()
{
int m,n;
char p;
while(scanf("%d%c%d",&n,&p,&m)!=EOF)
{
link* head;
link* temp;
initLink(head);
temp=head;
for(int i=0 ; i<n ; i++)
{
insert(temp);
temp->next->a=i+1; //创建链表
temp=temp->next;
}
temp->next=NULL;
temp=head;
while(head->next!=NULL)
{
for(int i=1;i<m;i++) //模拟约瑟夫过程 {
{
if(temp->next==NULL)
temp=head;
}
temp=temp->next;
}
if(temp->next==NULL)
{
printf("%d ",head->next->a);
destory(head);
}
else
{
printf("%d ",temp->next->a);
destory(temp);
}
}
printf("\n");
}
}
程序2
#include<iostream>
using namespace std;
void main()
{
int n,m,a[100001],k,i,j;
cin>>n;
if(n>100000)
{
cout<<"请重输";
return;
}
cin>>m;
for(i=1;i<=n;i++)
{
a[i]=1;
}
j=0;
k=0;
for(i=1;i<=n;i++)
{
if(a[i]==1)
{
j=j+a[i];
if(j==m)
{
j=0;
a[i]=0;
k++;
cout<<i<<" ";
}
}
if(i==n)
i=0;
}
}
七、实验心得
李孟琪:该实验利用数组实现线性表,算法简便,但产生很多不必要的消耗,下一步可以尝试采用单链表,双链表实现该问题。
李春阳:通过利用链表编写约瑟夫环,进一步掌握了约瑟夫环的原理,加深了对链表使用的理解
雷鹤:这次实验遇到的最大问题是拘泥于基本要求中的利用数组来实现线性表,并用线性表来实现约瑟夫环问题,在尝试用链表实现后问题变得简单了些;在插入元素这一步费不少时间,头尾节点的移动关系也需要理解。