题目描述

有n(n<100)个人依次围成一圈,从第1个人开始报数,数到第m个人出列,然后从出列的下一个人开始报数,数到第m个人又出列,…,如此反复到所有的人全部出列为止。设n个人的编号分别为1,2,…,n,打印出列的顺序。

输入

n和m。

输出

出列的顺序。

样例输入

4 17

样例输出

1 3 4 2

我们可以看到这个围圈报数(即约瑟夫问题),其实就是链表问题。我们通过这道题需要掌握的是循环单链表的写法(以c语言为例)

一、循环链表的写法

1.先定义链表的结构体

struct child{int data;struct child* next;
};

然后再全局变量定 “头节点”和“约瑟夫环的两个参数”

struct child* headnode;
int n,m;

下面,我们来定义两个函数,分别是“创建空节点”与“创建有数据的节点”

struct child* emptynode(){struct child* p = (struct child*)malloc(sizeof(struct child));p->data = NULL;p->next = NULL;return p;
}struct child* createnode(int num){struct child* p = (struct child*)malloc(sizeof(struct child));p->data = num;p->next = NULL;return p;
}

我们可以看出这两段代码的主要差别,其实就是p->data=NULL和p->data=num

接下来定义一个函数“createlistBytail”,以尾接法,创建循环单链表

void createlistBytail(struct child* headnode,int num){struct child* r=headnode;for (int i=2; i<=num; i++ ){struct child* s = createnode(i);s->next = r->next;r->next = s;r=s;} r->next = headnode;
}

其中需要注意的是,这段代码看似为单纯的创建单链表,其实我们在结尾处添加了一段代码

r->next = headnode;

这段代码保证了单链表的循环,也正因为这段代码,使得我们的单链表成功升级为循环单链表!

当然,为了检验我们的链表是否创建成功,我们可以写入这列代码,来遍历出链表的数据

void printlist(struct child* headnode){struct child* pMove = headnode;while(pMove) {printf("%d",pMove->data );pMove = pMove->next ;}
}

接下来,我们开始创建solve函数,实现围圈报数功能

void solve(struct child* headnode,int n,int m){int i,j;struct child* p;struct child* q;for(i=1;i<=n;i++){p = headnode;j = 1;for(j=1;j<m-1;j++){p = p->next ;}q = p->next ;printf("%d ",q->data );p->next = q->next ;headnode = p->next ;}
}

其中,我们需要注意的是 我们在进行第二个for循环时,j<m-1这个数值不要搞错。我们为什么要j<m-1呢?因为我们要保证p是在第m个人的前一个人,这样我们就可以使q指向p->next,也就是我们想要的那个第m个人,实现精准查找,然后精准“删除”。但是问题来了,我们为什么不直接将p指向第m个人呢,这样我们直接输出p不就好了么:(。非也非也!你只是想到了输出数值的事,但是后面的事你却没能想到。

我们在这段函数的主要任务是什么呢?1.输出第m个人2.删除m,让m前一个人接上m后一个人3.将领头人headnode变成m的下一个人,也就是说从m的下一个人开始报数。这样我们不难发现我们将p设为m的前一个人,是要将p-next指向q->next,实现删除m的目的,因为我们节点的指针能指向某节点的后面,却指向不了节点的前面,所以哦我们需要这样的一个p指向m前一个点。

最后,我们编写主函数,将上面的函数包装进去

其中我们要注意的是,创建空节点与数据节点不在主函数里。

int main(){struct child* headnode = createnode(1);scanf("%d %d",&n,&m);createlistBytail(headnode,n);//printlist(headnode);solve(headnode,n,m);return 0;
}

这样,我们的代码就算结束了。最后,给大家奉上“围圈报数”(即约瑟夫问题)的完整版代码

#include<stdio.h>
#include<stdlib.h>
struct child{int data;struct child* next;
};struct child* headnode;
int n,m;struct child* emptynode(){struct child* p = (struct child*)malloc(sizeof(struct child));p->data = NULL;p->next = NULL;return p;
}struct child* createnode(int num){struct child* p = (struct child*)malloc(sizeof(struct child));p->data = num;p->next = NULL;return p;
}void createlistBytail(struct child* headnode,int num){struct child* r=headnode;for (int i=2; i<=num; i++ ){struct child* s = createnode(i);s->next = r->next;r->next = s;r=s;} r->next = headnode;
}void printlist(struct child* headnode){struct child* pMove = headnode;while(pMove) {printf("%d",pMove->data );pMove = pMove->next ;}
}void solve(struct child* headnode,int n,int m){int i,j;struct child* p;struct child* q;for(i=1;i<=n;i++){p = headnode;j = 1;for(j=1;j<m-1;j++){p = p->next ;}q = p->next ;printf("%d ",q->data );p->next = q->next ;headnode = p->next ;}
}int main(){struct child* headnode = createnode(1);scanf("%d %d",&n,&m);createlistBytail(headnode,n);//printlist(headnode);solve(headnode,n,m);return 0;
}

问题 C: 【例2-3】围圈报数相关推荐

  1. 信息学奥赛一本通 2037:【例5.4】约瑟夫问题 | 1334:【例2-3】围圈报数 | 洛谷 P1996 约瑟夫问题

    [题目链接] ybt 2037:[例5.4]约瑟夫问题 ybt 1334:[例2-3]围圈报数 洛谷 P1996 约瑟夫问题 [题目考点] 1. 循环遍历数组 假设数组下标为1~n,循环控制变量i从1 ...

  2. 围圈报数c语言编程,59、1334:【例2-3】围圈报数(A)

    1334:[例2-3]围圈报数-AC [例3]设有n个人依次围成一圈,从第1个人开始报数, 数到第m个人出列,然后从出列的下一个人开始报数, 数到第m个人又出列,-,如此反复到所有的人全部出列为止. ...

  3. 1334:【例2-3】围圈报数

    题目描述] 有n个人依次围成一圈,从第1个人开始报数,数到第m个人出列,然后从出列的下一个人开始报数,数到第m个人又出列,-,如此反复到所有的人全部出列为止.设n个人的编号分别为1,2,-,n,打印出 ...

  4. 队列做题:1333:Blah数集(单调队列);1334:围圈报数

    1333:Blah数集(单调队列) 又是一种奇怪的数据结构(算法),见得太少了. 注意:不是优先队列(堆)哟!!!. 注意:集合中的元素不可以重复!!!. 讲解: https://blog.csdn. ...

  5. python围圈报数 青少年编程电子学会python编程等级考试三级真题解析2021年6月

    目录 python围圈报数 一.题目要求 1.编程实现 2.输入输出 3.评分标准

  6. 【Python】青少年蓝桥杯_每日一题_11.19_围圈报数

    编程实现 有 n 个人围成一个圈,按顺序排好号.然后从第一个人开始报数(从 1 到 3 报数),报到 3 的人退 出圈子,然后继续从 1 到 3 报数,直到最后留下一个人游戏结束,问最后留下的是原来第 ...

  7. 围圈报数(信息学奥赛一本通-T1334)

    [题目描述] 有n个人依次围成一圈,从第1个人开始报数,数到第m个人出列,然后从出列的下一个人开始报数,数到第m个人又出列,-,如此反复到所有的人全部出列为止.设n个人的编号分别为1,2,-,n,打印 ...

  8. Python编程之围圈报数

    问题描述:有n个人围成一圈,顺序排号.从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位. 源代码: #!/usr/bin/python # -*- coding ...

  9. C语言:围圈报数游戏

    游戏规则:有N个人围成一圈,顺序排号,从第一个人开始1到D报数,,凡报到D的人退出圈子(下场),问最后留下来的是原来的第几号? 逻辑思想:用布尔数组记下每个人的上场状态,1为上场,0为下场,开始游戏后 ...

最新文章

  1. 成功部署SD-WAN策略应注意的几个事项—Vecloud微云
  2. Linux文件查看命令图解
  3. java是什么格式_是java格式
  4. HDFS的副本存放策略(机架感知策略)
  5. 你的IP地址是不是经常被发现
  6. 监控 DNS 流量,预防安全隐患五大招!
  7. Spring 3 MVC异常处理程序
  8. MAC OS上JAVA1.6 升级1.7,以及 maven3.2.1配置
  9. camera(21)---MTK android AF调试总结
  10. ArcEngine二次开发_02(鼠标移过图层中显示特定的属性信息)
  11. SSM使用拦截器功能
  12. 典型相关分析 CCA
  13. 使用npm安装yarn
  14. 新浪微博PC端登录分析
  15. swift 框架大全
  16. 移动硬盘坏了数据可以恢复吗?新方法一看便知
  17. 守法公民 Law Abiding Citizen (2009)
  18. 目标检测:传统目标检测方法
  19. 计算机文化基础第二次作业-简答题,中传2018年秋计算机文化基础第二次作业-简答题...
  20. html实现数据的增删查改

热门文章

  1. 南方方洲号无人测量船系统简介
  2. Android之使用PopupWindow使用和总结
  3. Android之获取屏幕和视图高和宽
  4. Hibernate懒加载
  5. 一个基础的 HTML 文档有哪些标签?(3)
  6. php获取虚拟机ip,php如何获取用户的ip地址
  7. 曾凭一己之力推动物理学发展,是清华大学最年轻教授,世界却欠他一个诺贝尔奖!...
  8. 周杰伦新歌《说好不哭》彩蛋大汇总! | 今日最佳
  9. 一堂儿童科学实验课引起的思考:数学和化学有什么关系?
  10. 读书笔记-互联网思维必读10本书之一《免费》