题目

解答

  1. 法一:单循环链表

     #include<stdio.h>#include<stdlib.h>//定义单循环链表数据结构typedef struct CNode{int data;struct CNode *next;}CNode;typedef CNode *CLinkList;//初始化一个指向头节点的指针,使头指针->next=头指针,头指针->data不做处理void InitList_L(CLinkList *L){(*L) = (CLinkList)malloc(sizeof(CNode));if(!(*L))exit(-2);(*L)->next = *L;  }//头插法建立单循环链表int CreateList_HL(CLinkList *L,int s[],int n){ //二级指针int i;CLinkList p;*L = (CLinkList)malloc(sizeof(CNode));if(!(*L))exit(-2);(*L)->next = *L;          //只有一个头节点head,就让next指向自己for(i=0; i<n; i++){p = (CLinkList)malloc(sizeof(CNode));if(!p)exit(-2);p->data = s[i];            //录入数据 p->next = (*L)->next;   //将头指针所指向的下一个结点的地址,赋给新创建结点的next (*L)->next = p;            //将新创建的结点的地址赋给头指针的下一个结点}return 1;} //尾插法建立单循环链表int CreateList_TL(CLinkList *L,int s[],int n){int i;CLinkList p, q;  *L = (CLinkList)malloc(sizeof(CNode));if(!(*L))exit(-2);(*L)->next = *L;   //只有一个头节点head,就让next指向自己for(i=0,q=*L; i<n; i++){p = (CLinkList)malloc(sizeof(CNode));if(!p)exit(-2);p->data = s[i];  //录入数据 q->next = p;q = q->next;}q->next = *L;      //最后一个结点指向headreturn 1;}//求单循环链表的长度int ListLength(CLinkList L){CLinkList p;              int count;if(L){count = 0;p = L;             //p指向头结点  while(p->next!=L){ //p没到表头count++;p = p->next;}}return count;} //得到指向单循环链表第i个元素的指针CLinkList GetElemPtr(CLinkList L, int i){                                      int count;CLinkList p;if(L&&i>0){count = 1;p = L->next;while(p!=L && count<i){count++;p = p->next;}if(p!=L)   //L为头指针return p;}return NULL;}//单循环链表第i个位置插入元素eint ListInsert(CLinkList L, int i, int e){CLinkList p, s;int j;if(i<1 || i>ListLength(L)+1)  //插入位置不合理return 0;p = L;j = 0; while(j<i-1){  //寻找第i-1个结点p = p->next;++j;}s = (CLinkList)malloc(sizeof(CNode));if(!s)exit(-2);s->data = e;s->next = p->next;p->next = s;return 1;        } //单循环链表第i个位置删除元素eint ListDelete(CLinkList L, int i, int *e){CLinkList pre, p; int j;if(i<1 || i>ListLength(L))  //删除位置不合理return 0;pre = L;j = 1; while(pre->next && j<i){  //寻找第i个结点,并令pre指向其前驱 pre = pre->next;++j;}p = pre->next;pre->next = p->next;*e = p->data;free(p);p=NULL;return 1; }//遍历单循环链表void ListTraverse(CLinkList L){CLinkList p;p = L->next;   //p指向头结点,正向访问链表while(p!=L){printf("%d ",p->data);p = p->next;}printf("\n");}//判断单循环链表是否为空int ListEmpty(CLinkList L){if(L!=NULL && L->next==L)  //单循环链表存在并且只有头结点 return 1;elsereturn 0;}/*用单循环链表解决约瑟夫环问题(带头结点)这里的单循环链表使用了带头结点的,方便找到表头的位置,但是由于头结点不存储元素,因此需要跳过头结点链表插入删除都比较方便,不需要移动大量元素,只需要移动指针即可,适合这一类问题*/void Algo(CLinkList L,int k,int m){ //从编号为k的人开始数,数到m的那个人出队列int count,i,j;  //count表示每次从1开始数,i用来找编号为k的结点的前驱CLinkList pre,p;pre=L;count=1,i=1,j=1; /*寻找第k个结点,并令pre指向其前驱*/while(i<k){       if(pre->next==L) //跳过头结点pre=pre->next->next;elsepre = pre->next;++i;}while(L->next!=L){  //如果单循环链表不为空if(count==m){/*下一个结点不是头结点,直接删除*/if(pre->next!=L){  p=pre->next;printf("第%d次出环的元素是%d\n",j++,p->data);pre->next=p->next;free(p);p=NULL;count=1;}/*下一个结点是头结点,下下个结点不是头结点,跳过头结点,删除下下个结点(头结点不保存数据,因此不参与运算)*/else if(pre->next->next!=L){ p=pre->next->next;printf("第%d次出环的元素是%d\n",j++,p->data);pre->next->next=p->next;free(p);p=NULL;count=1;}/*下一个结点是头结点,下下个结点也是头结点,说明单循环链表已经为空了,只剩下头结点,因此跳出循环*/else  break;}count++;        //count代表要删除的结点数的数,始终在pre指向的结点之前if(pre->next==L) //跳过头结点pre=pre->next->next; //pre指向要删除结点的前一个结点elsepre = pre->next;     //pre指向要删除结点的前一个结点}}void main(){CLinkList L;int n=5,s[5]={1,2,3,4,5}; //假设5个人围坐一圈int k=3,m=2;              //第一次从编号为k的人开始数,数到m的那个人出队列CreateList_TL(&L,s,n);    //头插法建立单循环链表ListTraverse(L);          //遍历原始队列printf("假设第一次从编号为%d的人开始数,数到%d的那个人出环\n",k,m);Algo(L,k,m);       //用单循环链表解决约瑟夫环问题(带头结点)}
    
  2. 法二:循环数组

       /*用循环数组解决约瑟夫环问题解决问题的难点有两个:1、如何求下一个的人的位置:在循环数组中向后移动采用:(k+l)%n2、此人出圈后对这个人的位置如何处理:先将出圈人的位置打印输出,然后将其位置元素设置为0,表示它已出圈,以后见到它就直接跳过去*/void Algo2(int s[],int n,int k0,int m){  //开始一共有n个人,从第k0个人开始数,数到m的那个人出队列int i,j,k=k0-1;     //元素访问的下标为 k,初始时从第k0个人开始数for(i=0;i<n;i++){   //总共循环n次,每循环一次,出队一个元素,k在循环中会不断的运动j=1;            //j表示数的数,初始为1while(j<m){     //如果还没有数到mwhile(s[k]==0) //如果s[k]为0,证明它已经出圈了,则跳过它k=(k+1)%n; j++;         //数下一个数k=(k+1)%n;   //数组下标向后走一步}while(s[k]==0) //如果数到m发现它出圈了,则跳过它,找到第一个没出圈的数k=(k+1)%n;printf("第%d次出环的元素是%d\n",i+1,s[k]); //先将出圈人的位置打印输出s[k]=0; //然后将其位置元素设置为0,表示它已经出圈}}void main(){int n=5,s[5]={1,2,3,4,5}; //假设5个人围坐一圈int k=3,m=2;              //第一次从编号为k的人开始数,数到m的那个人出队列printf("假设第一次从编号为%d的人开始数,数到%d的那个人出环\n",k,m);Algo2(s,n,k,m);    //用循环数组解决约瑟夫环问题}
    
  3. 法三:递归

     /*用递归解决约瑟夫环问题n指的是总人数,m指的是每次最大报到的数值,i是第i次,该函数每次可以求出第i次扔海里的人的编号*/int Algo3(int n,int m,int i){if(i==1)return (n+m-1)%n;elsereturn (Algo3(n-1,m,i-1)+m)%n;}void main(){int n=5; //假设5个人围坐一圈int m=2; //数到2的那个人出环             printf("假设第一次从编号为1的人开始数,数到%d的那个人出环\n",m);for(int i=1;i<=n;i++)printf("第%d次出环的元素是%d\n",i,Algo3(n,m,i)+1); //因为求出的结果是数组中的下标,最终的编号还要加1}
    
  4. 法四:迭代

     /*用迭代解决约瑟夫环问题递推公式:f(N,M)=(f(N−1,M)+M)%Nf(N,M)表示,N个人报数,每报到M时杀掉那个人,最终胜利者的编号f(N−1,M)表示,N-1个人报数,每报到M时杀掉那个人,最终胜利者的编号*/int Algo4(int n,int m){int i,p=0;for(i=2;i<=n;i++){p=(p+m)%i;}return p+1; //因为求出的结果是数组中的下标,最终的编号还要加1}void main(){int n=5; //假设5个人围坐一圈int m=2; //数到2的那个人出环printf("假设第一次从编号为1的人开始数,最后出环的是:%d\n",Algo4(n,m));}
    

C语言解决约瑟夫环问题相关推荐

  1. C语言解决约瑟夫环问题 详细注释

    约瑟夫环算法是: n 个人围成一圈,每个人都有一个互不相同的密码,该密码是一个整数值,选择一个人作为起点,然后顺时针从 1 到 k(k为起点人手中的密码值)数数.数到 k 的人退出圈子,然后从下一个人 ...

  2. C语言使用数组和循环解决约瑟夫环问题

    C语言使用数组和循环解决约瑟夫环问题 约瑟夫入狱,监狱内共有 33 个犯人.某日 33 名犯人围成一圈,从第一个犯人开始报数,报到数字 7 的犯人出列, 被枪毙,下一名犯人重新从 1 开始报数.依次类 ...

  3. PHP解决约瑟夫环问题

    PHP解决约瑟夫环问题 一.总结 二.PHP解决约瑟夫环问题 约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到 ...

  4. 循环链表解决约瑟夫环问题

    约瑟夫环问题可以简单的使用数组的方式实现,但是现在我使用循环链表的方法来实现,因为上午看到一道面试题规定使用循环链表解决约瑟夫环问题. 什么是约瑟夫环? "约瑟夫环是一个数学的应用问题:已知 ...

  5. 用java解决约瑟夫循环问题,Java实现循环列表解决约瑟夫环问题

    约瑟夫环:共有n个人围成一圈,从1开始报数,数到m的人出圈,求最后幸运者序号?? 下面用Java实现循环列表解决这个问题: package com.iteye.ljmdbc7a; import jav ...

  6. C语言解决约瑟夫问题详解的代码

    C语言解决约瑟夫问题详解的代码 参考文章: (1)C语言解决约瑟夫问题详解的代码 (2)https://www.cnblogs.com/odsxe/p/10791049.html (3)https:/ ...

  7. java实现环形链表解决约瑟夫环问题

    什么是环形链表? 环形链表就是单向链表的基础上让链表的首尾相连,形成一个环,这就是一个循环链表. 什么是约瑟夫环问题? 约瑟夫环如下: 约瑟夫问题是个著名的问题:N个人围成一圈,第一个人从1开始报数, ...

  8. c语言约瑟夫环分函数,c语言实现约瑟夫环问题

    <c语言实现约瑟夫环问题>由会员分享,可在线阅读,更多相关<c语言实现约瑟夫环问题(16页珍藏版)>请在人人文库网上搜索. 1.一)基本问题1问题描述设有编号为1,2,小的n ...

  9. 【C语言】循环链表解决约瑟夫环问题

    好玩的约瑟夫环:有M个人,编号分别为1到M,玩约瑟夫环游戏,最初时按编号顺序排成队列:每遍游戏开始时,有一个正整数报数密码N,队列中人依次围坐成一圈,从队首的人开始报数,报到N的人出列,然后再从出列的 ...

  10. 【图解经典算法题】如何用一行代码解决约瑟夫环问题

    约瑟夫环问题算是很经典的题了,估计大家都听说过,然后我就在一次笔试中遇到了,下面我就用 3 种方法来详细讲解一下这道题,最后一种方法学了之后保证让你可以让你装逼. 问题描述:编号为 1-N 的 N 个 ...

最新文章

  1. 非常实用的 Python 技巧
  2. R语言使用ggplot2包的快速可视化函数qplot绘制基础直方图实战
  3. OpenCV移植各向异性图像分割间隙流体的实例(附完整代码)
  4. xms和xmx为什么要相同_股民为什么要做股票配资?
  5. 旁瓣对消原理_雷达天线旁瓣对消技术
  6. get_children 方法里面参数 iv_as_copy 有什么用?
  7. 修改数组(洛谷P7285题题解,C++语言描述)
  8. 云服务器 ECS > 块存储 > 块存储介绍 > 块存储概述 请输入关键词
  9. 深入浅出ObjC之消息
  10. 服务器磁盘管理 知识点
  11. html+加粗+w3c,HTML5教程:html标签属性通过w3c验证
  12. 如何使用计算机检测网络正常使用,如何测试网速? 本地测网速的几种方法分享...
  13. 复盘图像双线性插值推导细节
  14. java 用word模板打标签,并插入图片 动态生成word
  15. 函数论_E.C.Tichmarsh_Page 4 级数一致收敛的魏尔斯特拉斯 M-判别法 的推广
  16. SAP 生产成本明细报表
  17. Chef入门详解 Chef安装 Chef使用
  18. python生产实战 python 闭包之庖丁解牛篇
  19. Java通过freemarker生成word文档
  20. Android - TextView Ellipsize属性

热门文章

  1. 软件测试达内视频笔记(一)
  2. 3t硬盘 xp_如何在Windows XP SP3 32位系统下识别3T容量GPT格式硬盘
  3. 计算机程序设计语言有哪几类,计算机程序设计语言可以分为哪三类?
  4. c语言入门经典+第5版+习题答案,《C语言入门经典(第5版)》—甲虎网一站式图书批发平台...
  5. Windows下的TFTP传输文件
  6. Dynamips GNS3
  7. 揭秘:为何冬天成都游戏玩家整体水平会下滑?
  8. FLV文件格式官方规范详解
  9. Android视频编码的坑
  10. BIM族库下载——Revit栏杆族库