c语言实现约瑟夫环问题.docx
- 文档编号:6357803
- 上传时间:2023-01-05
- 格式:DOCX
- 页数:16
- 大小:108.63KB
c语言实现约瑟夫环问题.docx
《c语言实现约瑟夫环问题.docx》由会员分享,可在线阅读,更多相关《c语言实现约瑟夫环问题.docx(16页珍藏版)》请在冰豆网上搜索。
c语言实现约瑟夫环问题
(一)基本问题
1.问题描述
设有编号为1,2,…,n的n(n>0)个人围成一个圈,每个人持有一个密码m。
从第一个人开始报数,报到m时停止报数,报m的人出圈,再从他的下一个人起重新报数,报到m时停止报数,报m的出圈,……,如此下去,直到所有人全部出圈为止。
当任意给定n和m后,设计算法求n个人出圈的次序。
建立模型,确定存储结构。
对任意n个人,密码为m,实现约瑟夫环问题。
2.数据结构设计
首先,设计实现约瑟夫环问题的存储结构。
由于约瑟夫环问题本身具有循环性质,考虑采用循环链表,为了统一对表中任意结点的操作,循环链表不带头结点。
将循环链表的结点定义为如下结构类型:
structNode
{
intdata;
Node*next;
};
其次,建立一个不带头结点的循环链表并由头指针first指示
3.算法设计
1、工作指针first,r,s,p,q初始化
2、输入人数(n)和报数(m)
3、循环n次,用尾插法创建链表
Node*q;
for(inti=1;i<=n;i++)
{
Node*p;
p=newNode;
p->data=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=newNode;计数器初始化i=1;
6、循环n次删除结点并报出位置(其中第一个人后移k个)
当i 移动指针m-2次p=p->next; 删除p结点的后一结点q q=p->next; p->next=q->next; *L=p->next; 报出位置后Deleteq; 计数器i++; 运行流程图 代码和相关解释 #include usingnamespacestd; structNode//循环节点的定义 { intdata;//编号 Node*next; }; Node*CreateList(Node*L,int&n,int&m);//建立约瑟夫环函数 voidJoseph(Node*L,intn,intm);//输出每次出列号数函数 Node*DeleteList(Node**L,inti,Node*q);//寻找每次出列人的号数 intLengthList(Node*L);//计算环上所有人数函数 voidmain()//主函数 //在主函数中,完成人数(n)和报数(m)的输入和工作指针的初始化 { Node*L; L=NULL;//初始化尾指针 intn,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(inti=1;i<=n;i++) { Node*p; p=newNode; p->data=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);}//返回尾指针 elsecout<<"尾指针异常! "< } voidJoseph(Node*L,intn,intm)//输出每次出列的人 { intk; cout<<"请输入第一个报数人: "; cin>>k; if(k<1||k>n){cout<<"请输入1-"< else { cout<<"\n出列顺序: \n"; for(inti=1;i { Node*q=newNode; if(i==1)q=DeleteList(&L,k+m-1,q);//第一个出列人的号数 elseq=DeleteList(&L,m,q); cout<<"号数: "< deleteq;//释放出列人的存储空间 } cout<<"最后一个出列号数是: "< } } Node*DeleteList(Node**L,inti,Node*q)//寻找每次出列的人 { if(i==1)i+=LengthList(*L);//顺序依次出列情况的处理方式 Node*p; p=*L; intj=0; while(j q=p->next; p->next=p->next->next; *L=p->next; return(q); } intLengthList(Node*L)//计算环上的人数 { if(L){cout<<"尾指针错误! "< else { inti=1; Node*p=L->next; while(p! =L) { i++; p=p->next; } return(i); } } 复杂度分析: for(inti=1;i<=n;i++) { Node*p; p=newNode; 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; intj=0; while(j q=p->next; p->next=p->next->next; *L=p->next; return(q); 时间复杂度: O(n2) 算法的空间复杂度: O(n2) 4.界面设计 5.运行、测试与分析 (二)采用顺序存储结构如何实现约瑟夫环问题 代码和解释 #include #include #include #defineMaxSize50 typedefcharElemType; typedefstructSeqlist {//线性表顺序存储结构定义 ElemType*elem[MaxSize];//存放顺序表数据元素 intlength;//当前长度 }*JSeqlist;//线性表存储结构类型名 JSeqlistInt_SeqList(void) {//顺序表初始化 JSeqlistL; L=(JSeqlist)malloc(sizeof(structSeqlist)); if(L! =NULL) L->length=0; else printf("超出围! ! "); returnL; } ElemType*Locate_SeqList(JSeqlistL,intp) {//查找线性表中下标为P的元素 if(p>=0&&L->length) return(L->elem[p]); else {printf("顺序表中不存在相关元素"); returnNULL; } } intInsert_SeqList(JSeqlistL,inti,ElemType*x) {//在顺序表中指定元素前插入X intj; if(L->length==MaxSize)//L.length是最后一个元素的位置 {printf("线性表已满,无法进行插入操作! ! ! ! \n"); return0; } if(i<0||i>L->length) {printf("插入位置不对,超出顺序表长度\n"); return0; } if(i==0) {L->elem[i]=x; L->length=L->length+1; return1; } for(j=L->length;j>=i;j--) {L->elem[j]=x;} L->length++; return1; } intDelete_JSeqlist(JSeqlistL,inti) {//在顺序表中删除第i个元素 intj; if(i<0||i>L->length-1) { printf("删除位置不对,超出顺序表的长度啦\n"); return0; } for(j=i;j L->elem[j]=L->elem[j+1]; L->length--; return1; } voidjosephus(JSeqlistL,intstart,intm) {//josephus问题求解的非常牛逼的函数 ints,i; ElemType*w; s=start-1; for(i=L->length;i>0;i--) { s=(s+m-1)%i; w=Locate_SeqList(L,s); printf("出列人员为: %s\n",w); Delete_JSeqlist(L,s); } } intmain(void) { JSeqlistJosephus; intn,m,i,k,s; Josephus=Int_SeqList();//顺序表初始化 printf("约瑟夫环问题顺序表求解_愚人节特别版\n\n"); printf("请输入本问题中总人数m="); scanf("%d",&n); printf("请输入本问题开始人员的位置S="); scanf("%d",&s); printf("请输入本问题的计数值m="); scanf("%d",&m); printf("请输入本问题中这些人的名字\n"); for(i=0;i { printf("第%d位置的人员的名字为: ",(i+1)); Josephus->elem[i]=(ElemType*)calloc(10,sizeof(char)); scanf("%s",Josephus->elem[i]); k=Insert_SeqList(Josephus,i,Josephus->elem[i]); if(k==0) exit (1); } josephus(Josephus,s,m); free(Josephus); getchar(); return0; } 运行结果 (三)密码不同 #include structCList { intpassword; intnumber; structCList*next; }; typedefstructCListCNode; typedefCNode*CLink; CLinkCreateList(intlength) { CLinkhead; CLinkbefore; CLinknew_node; inti; head=newCNode; if(head==NULL) returnNULL; cout<<"PleaseInputPassword1: "< cin>>head->password; head->number=1; head->next=NULL; before=head; for(i=1;i { new_node=newCNode; if(new_node==NULL) returnNULL; new_node->number=i+1; cout<<"PleaseInputPassword"< "< cin>>new_node->password; new_node->next=NULL; before->next=new_node; before=new_node; } new_node->next=head; returnhead; } intmain() { CLinkhead; CLinkptr,back,last; inti,j,m,n; cout<<"PleaseInputtheNumberofPersons: "< cin>>n; cout<<"PleaseInputtheFirstPasswordM: "< cin>>m; head=CreateList(n); ptr=head; for(i=0;i { for(j=0;j { back=ptr;//定位最后一个数的接点赋值给back ptr=back->next; } cout<<"第"< "< m=ptr->password; if(ptr==head) { last=head; while(last->next! =head) last=last->next; last->next=head->next; deleteptr; ptr=last->next; head=ptr; } else { back->next=ptr->next; deleteptr; ptr=back->next; } } return0; } 运行结果 (三)心得体会: 1.编程是个很细致的工作,尤其是在写顺序表的时候,涉及的函数很多,函数名中最初为了看在清晰,涉及成单词首字母是大写的,但是后来在函数调用的时候,就忘记了最初命名的时候是大写的了,导致编译的时候不能识别。 2.通过这个实验,理解了数据结构是数学在编程中的应用,是程序涉及和算法设计的基础,在计算机相关学科总占有举足轻重的地位
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 实现 约瑟夫 问题