基本算法——约瑟夫环问题

关于约瑟夫环问题,我们可以从两种思路去实现,一种是用数组,另一种是采用链表。

用数组方法实现代码:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #define M 8
 5 int find(int *arr, int len);
 6 int main(int argc, char* argv[])
 7 {
 8     int size = atoi(argv[1]);
 9     int* arr = (int*)calloc(size, 4);
10     int index ;
11     for(index = 0; index < size ; index ++)
12     {
13         arr[index] = index + 1 ;
14     }
15     printf("\nwinner: %d \n", find(arr, size));
16     return 0 ;
17 }
18 int find(int *arr, int len)
19 {
20     int index , step ;
21     int size = len ;
22     index = 0 ;
23     step = 0 ;
24     while(len > 1)
25     {
26         if(arr[index] != 0)
27         {
28             ++step ;
29             if(step == M)
30             {
31                 printf("%3d", index + 1);
32                 arr[index] = 0 ;
33                 step = 0 ;
34                 len -- ;
35             }
36         }
37         index = (index + 1) % size ;
38     }
39     for(index = 0 ; index < size ; index ++)
40     {
41         if(arr[index] != 0)
42         {
43             return arr[index] ;
44         }
45     }
46 }

该方法就是采用一个计数,同时还要有一个变量来跟随数组下标,每当计数与我们规定的退出值相等时,将数组中当前下标的值置为0,无形中增加了许多判断。

用链表方法实现代码:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #define M 8
 5 typedef struct tag
 6 {
 7     int num;
 8     struct tag *next;
 9 }Node, *pNode;
10 void link_create(pNode *head, int size);
11 void link_del(pNode *head, int a);
12 int find(pNode *head, int size);
13 int main(int argc, char* argv[])
14 {
15     int size = atoi(argv[1]);
16     pNode head;
17     link_create(&head, size);
18     printf("\nwinner: %d \n", find(&head, size));
19     return 0 ;
20 }
21
22 int find(pNode *head, int size)
23 {
24     pNode  pcur = *head, ppre = NULL;
25     int step = 1;
26     while(size > 1)
27     {
28         if(step == M)
29         {
30             step = 1;
31             printf("%3d", pcur->num);
32             pNode p = pcur;
33             ppre->next = pcur->next;
34             free(p);
35             pcur = ppre->next;
36             -- size;
37         }
38         else
39         {
40             ++ step;
41             ppre = pcur;
42             pcur = pcur->next;
43         }
44     }
45     return pcur->num;
46 }
47
48 void link_create(pNode *head, int size)
49 {
50     pNode p;
51     *head = NULL;
52     while(size > 0)
53     {
54         p = (pNode)calloc(1, sizeof(Node));
55         p->num = size;
56         p->next = *head;
57         *head = p;
58         -- size;
59     }
60     p = *head;
61     while(p->next)
62     {
63         p = p->next;
64     }
65     p->next = *head;
66 }

在这里,我们创建一个链表环,这样,每次计数增加时,链表会指向下一个,无需我们再去跟踪该位置是哪个,我们只需判断计数是否为我们规定的退出值,让链表一直循环即可,当链表中只剩下一个元素是,该值就是我们的胜利者。

在该链表中,我们采用了一种创建环的方法,即将链表的尾指针指向头指针,这里需要注意一下。

时间: 2024-08-25 16:25:42

基本算法——约瑟夫环问题的相关文章

趣味算法--约瑟夫环问题

问题描述 已知n个人(以编号1,2,3,...,n分别表示)围坐在一张圆桌上.指定编号为k的人开始从1报数,数到m的那个人出列:出列那个人的下一位又从1开始报数,数到m的那个人出列:以此规则重复下去,直到圆桌上的人全部出列. 分析解决 解决方法主要有逻辑分析.数学分析法. 逻辑分析:就是按照游戏规则一个个报数,报到m的人出局,结构层次简单清晰明了.这种方式实现主要采用顺序表实现 数学分析:采用数学方式归纳统计分析出每次出局人的规律,直接得出每次出局的人,然后以代码实现.这种方法需要较强的数学分析

算法:约瑟夫环问题

算法:约瑟夫环问题 [写在前面] 由于本人天生驽钝,所写代码和描述可能不堪入目,高手请移步.但是我一直在努力记录一下有用的知识点,给自己给朋友用,只是希望对大家有帮助. [问题描述] 约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从第一个人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出列:依此规律重复下去,求最后一个出圈的人的标号. [代码] void JOSEF(int n,int m) //:n个人

【算法题目】约瑟夫环问题

题目来源:<剑指offer>面试题45 题目:0,1,...,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字.求出这个圆圈里剩下的最后一个数字. 解法一:经典解法,用环形链表模拟圆圈.这种方法每删除一个数字需要m步运算,总共有n个数字,因此总的时间复杂度是O(mn).同时这种思路还需要一个辅助链表来模拟圆圈,其空间复杂度是O(n). int LastRemaining(unsigned int n, unsigned int m) { if (n < 1 ||

cdoj525-猴子选大王 (约瑟夫环)

http://acm.uestc.edu.cn/#/problem/show/525 猴子选大王 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 有m个猴子围成一圈,按顺时针编号,分别为1到m.现打算从中选出一个大王.经过协商,决定选大王的规则如下:从第一个开始顺时针报数,报到n的猴子出圈,紧接着从下一个又从1顺时针循环报数,...,如此下去,最后剩

HDU 3089 (快速约瑟夫环)

Josephus again Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 652    Accepted Submission(s): 181 Problem Description In our Jesephus game, we start with n people numbered 1 to n around a circle

约瑟夫环的C语言数组实现

约瑟夫环问题的具体描述是:设有编号为1,2,--,n的n个(n>0)个人围成一个圈,从第1个人开始报数,报到m时停止报数,报m的人出圈,才从他的下一个人起重新报数,报到m时停止报数,报m的出圈,--,如此下去,知道剩余1个人为止.当任意给定n和m后,设计算法求n个人出圈的次序. 一开始看到这这个题目就是觉得这是一个环形的,想到了用链表和用指针,然后看题目的要求是使用数组实现.就先暂时放弃用链表的办法,用数组实现之后再用链表来实现. 一开始的思路是: 1.建立一个长度为n的数组. 2.取出位置编号

C语言数组实现约瑟夫环问题,以及对其进行时间复杂度分析

尝试表达 本人试着去表达约瑟夫环问题:一群人围成一个圈,作这样的一个游戏,选定一个人作起点以及数数的方向,这个人先数1,到下一个人数2,直到数到游戏规则约定那个数的人,比如是3,数到3的那个人就离开这个游戏:按这样的规则,剩下一个人,游戏就结束,这个人就为赢家.(读者可以试着表达,不认同,直接忽略) 抽象分析 这个人就是一个数据个体,数据结点,数据元素.上面产生的数据结构为:单方向循环的链.可以用链表实现,也可以用数组来实现. 链表到数组的迁移 人(数据元素. 数据结点.数据个体) 结点关系 (

约瑟夫环(N个人围桌,C语言,数据结构)

约瑟夫环问题(C语言.数据结构版) 一.问题描述 N个人围城一桌(首位相连),约定从1报数,报到数为k的人出局,然后下一位又从1开始报,以此类推.最后留下的人获胜.(有很多类似问题,如猴子选代王等等,解法都一样) 二.思路分析 (1)可将人的顺序简单编号,从1到N: (2)构造一个循环链表,可以解决首位相连的问题,同时如果将人的编号改为人名或者其他比较方便 (3)将人的编号插入到结构体的Data域: (4)遍历人的编号,输出参与的人的编号: (5)开始报数,从头报数,报到k的人出局(删除次结点)

组合数学--约瑟夫环问题 Josephus

约瑟夫斯问题(有时也称为约瑟夫斯置换),是一个出现在计算机科学和数学中的问题.在计算机编程的算法中,类似问题又称为约瑟夫环. 有n个囚犯站成一个圆圈,准备处决.首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人. 接着,再越过k-1个人,并杀掉第k个人.这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着. 问题是,给定了n和k,一开始要站在什么地方才能避免被处决? 问题是以弗拉维奥·约瑟夫斯命名的,它是1世纪的一名犹太历史学家.他在自己的日记中写道,