本文将用两种方式(数组和循环链表)求解约瑟夫环问题,为了更好理解,本文将从洛谷的P1996 约瑟夫问题出发。

题目描述

n个人围成一圈,从第一个人开始报数,数到 m的人出列,再由下一个人重新从1开始报数,数到 m的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。

输入格式

输入两个整数 n,m。

输出格式

输出一行 n个整数,按顺序输出每个出圈人的编号。

输入输出样例

输入

10 3

输出

3 6 9 2 7 1 8 5 10 4

说明/提示

1≤m,n≤100

方法一(数组):

解题思路:创建一个大小为n的数组用来表示n个人,同时用给数组元素赋值0或1表示该人的生死状态(0为生,1为死),同时设置一个flag用来表示当前淘汰的人数,当淘汰人数为n-1个人就跳出循环。

代码实现:

#include <stdio.h>
int main() {int n, q, i = 0, count = 1, flag = 0;printf("人数:");scanf("%d", &n);//输入人数getchar();printf("报到哪个数被杀死:");scanf("%d", &q);//输入报到哪个数死int a[n];for (i = 0; i < n; i++) {//给每个人设置“生”的状态a[i] = 0;}i = 0;printf("杀死顺序(下标):");while (1) {if (flag == n - 1) break;//当只剩下一个人时,跳出循环if (a[i] == 1) i++;//如果该人为死亡的状态,则跳过该人else {if (count == q) {//满足被杀死的条件a[i] = 1;//设置死亡状态flag++;//死亡人数加一printf("%d ", i);//输出这一次死亡的人的编号count = 1;//重置报数i++;//移动到下一个人开始} else {//不满足被杀死的状态count++;//继续报数i++;}}if (i == n) i = 0;//由于数组下标从0开始,所以当i=n时,应该是移动到第一个人了}printf("\n存活(下标):");for (i = 0;; i++) {if (a[i] != 1) {//输出最后存活的人printf("%d", i);break;}}return 0;
}

该方法一般为约瑟夫环问题的常见方法,但时间复杂度较高,而下面的方法可以帮助我们更好的理解循环链表的结构。

方法二(循环链表):

解题思路:

创建一个循环链表,这样可以看成一群人围成一圈的状态,并在头结点开始给人从1开始赋值表示编号,另外创建一个大小为n的数组用来储存死亡顺序(编号),每当有人死亡时,就把该人的编号储存到数组中,同时把该人从链表中删去。还需设计一个flag来表示死亡人数,当死亡人数为n-1人时就跳出循环。

代码实现:

创建循环链表函数Creat:

LINK* Creat(int n) {//该函数用来创建一个循环链表并返回该链表的尾结点LINK *head = NULL,*p = NULL, *pr = NULL;//head用来表示头节点,p用来申请内存空间,pr用来表示当前链表的尾结点int i;for(i = 1;i <= n;i++)//从1开始创建n个链表结点并依次赋值为i{p = (LINK*)malloc(sizeof(LINK));//申请动态内存if(p == NULL){printf("ERROR");return NULL;}p->id = i;if(head == NULL)//如果头节点为空指针,则把p赋给head{head = p;} else {//否则就用尾插法创建链表pr->next = p;}pr = p;//将pr赋值为指向当前链表最后一个结点}pr->next = head;//将最后一个节点的next指向head以构成循环链表return pr;//返回尾结点
}

用于确定出圈顺序的函数YueSeFu:

void YueSeFu(LINK* tail, int n, int m, int* a) {int count = 0,  flag = 0;//设置报数值和死亡人数值LINK* p = tail->next, *q = tail;//定义p为头指针,q为p前一个结点的指针while (flag < n - 1) {//死亡人数没有达到n-1count++;//报数if (count == m) {//满足出圈条件*a = p->id;//记录当前出圈者的编号a++;//让数组移向下一个值q->next = p->next;//让p的上一个结点的指针指向p的下一个结点free(p);//释放当前结点p = q->next;//p移动到下一个人count = 0;//重新开始报数flag++;//死亡人数加一} else {//不满足就移向下一个人q = p;p = p->next;}}*a = p->id;//记录最后一个人的编号free(p);
}

完整代码:

#include <stdio.h>
#include <stdlib.h>
typedef struct link {int id;struct link* next;
} LINK;LINK* Creat(int n);
void YueSeFu(LINK* head, int n, int m, int* a);
void DisplyLINK (LINK *head);int main(void) {int n, m;//n为总人数,m为出圈时报的数scanf("%d%d", &n, &m);int a[n];LINK* tail = NULL;//定义尾指针tail = Creat(n);//创建一个循环链表并得到尾指针YueSeFu(tail, n, m, a);for (int i = 0; i < n; i++) {//打印出圈顺序(编号)printf("%d ", a[i]);}
}LINK* Creat(int n) {LINK *head = NULL,*p = NULL, *pr = NULL;int i;for(i = 1;i <= n;i++){p = (LINK*)malloc(sizeof(LINK));if(p == NULL){printf("动态内存分配失败");return NULL;}p->id = i;if(head == NULL){head = p;}else{pr->next = p;}pr = p;}p->next = head;return pr;
}void YueSeFu(LINK* tail, int n, int m, int* a) {int count = 0, sum = 0;LINK* p = tail->next, *q = tail;while (sum < n - 1) {count++;if (count == m) {q->next = p->next;*a = p->id;free(p);p = q->next;count = 0;sum++;a++;} else {q=p;p=p->next;}}*a = p->id;free(p);
}

约瑟夫环问题(C语言数组和循环链表)相关推荐

  1. 深度剖析Josephus ring(约瑟夫环)C语言版

    深度剖析Josephus ring(约瑟夫环)C语言版 鉴于C语言更适合展示算法的底层设计,并且便于读者的研究与思考,故而小编使用C语言来展示约瑟夫环的精巧与奥妙. Hello!!各位同学们,欢迎来到 ...

  2. 数据结构—约瑟夫环问题(C语言版)

    目录 首先什么是约瑟夫环 约瑟夫环实现方式 一.创建结构体变量 二.初始化链表 三.构建循环链表 四.删除链表 五.完整代码及注释讲解 首先什么是约瑟夫环 约瑟夫环是循环链表中的一个经典问题:题目描述 ...

  3. 约瑟夫环的c语言描述

    约瑟夫环的c语言描述 问题描述 代码(C语言) 问题描述 约瑟夫(Joseph)问题的一种描述是:编号为1,2,-,n的n个人按顺时针方向围坐一圈.每人持有一个密码(正整数).一开始任选一个正整数作为 ...

  4. (猴子选王)约瑟夫环方法4种方法之一——循环链表法

    话都在代码里 题目 //约瑟夫环的循环链表解法 #include <stdlib.h> #include <malloc.h> #include <stdio.h> ...

  5. 约瑟夫环双向链表c语言实,双向链表与约瑟夫环代码

    双向链表 //注意:该文件操作的链表为带头结点双向链表,头结点数据为-1 #include #include #include #define OK 1 #define ERROR 0 typedef ...

  6. 约瑟夫环数据结构c语言程序,约瑟夫环问题详解(C语言链表实现)

    约瑟夫环问题,是一个经典的循环 出列顺序依次为: 编号为 3 的人开始数 1,然后 4 数 2,所以 4 先出列: 4 出列后,从 5 开始数 1,1 数 2,所以 1 出列: 1 出列后,从 2 开 ...

  7. 约瑟夫环(c语言程序完整版)

    约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3-n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出列: ...

  8. 约瑟夫环数据结构c语言程序,数据结构的C语言(类C语言)--单向循环链表--约瑟夫环...

    代码区 约瑟夫环:用类C语言实现!!!可以成功运行!!!不是仅仅的算法,而是实实在在的类C #include #include typedef int ElemType; typedef struct ...

  9. 约瑟夫环c语言循环指针,约瑟夫环(c语言)(双循环、单循环)

    /*题目: 耶稣又15个门徒,其中有一个时出卖耶稣的叛徒,请用排除法找出这位门徒:15人围坐一圈,从第一个开始报号:1,2,3,1,2,3...凡是报到"3"的退出圈子,最后留在圈 ...

最新文章

  1. 孙立岩 python-basic: 用于学习python基础的课件(五六七八九十)
  2. 登上Science子刊,神经科学再次启发DNN设计!中科院揭秘介观自组织反向传播机制...
  3. 如何让linux的history命令显示时间记录
  4. 字符串中子序列出现次数
  5. 本地计算机上的OracleOraDb11g_home2TNSListener服务启动又停止了。一些服务自动停止,如果他们没有什么可做的 ....
  6. 拼多多4.5元手表使用功能图
  7. android相册管理,Piktures - 最优雅的相册管理 - Android 应用 - 【最美应用】
  8. asp.net Linux 界面,在 ASP.NET 中实现不同角色的用户使用不同登录界面的方法
  9. GDI+ 使用指南(basic guiding of GDI plus )
  10. 实时备份工具之inotify+rsync
  11. Jeecg_3.6新版本功能专题讲解 - 公开课(自定义表单、数据权限)
  12. 产生随机小数_如果取到小数区间内的任一数字?
  13. python英文版怎么改成中文版_“PyQt的Qt Designer菜单是中文版的,怎么改成英文的“python的qt designer教程...
  14. ASP.net防止SQL注入方法
  15. 《计算机操作系统》第四版(汤小丹考研版) 全书知识梳理
  16. C++卡常数之内存优化
  17. 常见音频格式大盘点分析
  18. 图论基础——启发式搜索
  19. thinkphp前台模板运算符
  20. 简述关于ASP.NET MVC与.NET CORE 的区别

热门文章

  1. 使用plt.savefig()方法保存绘图时出现图片全白或全黑的问题
  2. Python采集网站ip代理, 检测IP代理是否可用,构建自己的ip代理池
  3. Common Weakness Enumeration (CWE) 2021 Lastest
  4. 9.app后端选择什么服务器
  5. 河北中考实验计算机分数,河北中考总分多少2020
  6. [转]海量存储检索原理系列文章
  7. Eclipse显示空白符号的具体设置
  8. sizeof关键字使用方法及实例演示
  9. Git之搭建Git服务器
  10. 在Android中访问内置SE和基于SE的卡模拟(一)