约瑟夫问题,“遍历”思想.(C语言实现)

来源:互联网 发布:男士脸型与发型知乎 编辑:程序博客网 时间:2024/05/19 12:27

题目:
一个旅行社要从N个游客中选出一名游客,为他提供免费旅行服务,选择方法是让N个游客围成一个圆圈,然后从信封中取出一张纸条,用上面写着的正整数M作为报数值,第一个人从1开始一个人一个人按顺时针报数,报到第M个游客时,令其出列。然后再从下一个人开始,从1顺时针报数,报到第M个游客,再令其出列……,直到圆圈中只剩一个人为止。此人即为优胜者,将获免费旅行服务,例如N=8,M=3,出列的顺序将为3、6、1、5、2、8、4,最初编号为7的游客将获免费旅游服务。
——《C语言程序设计实验与课程设计教程》清华出版社,游洪跃、彭骏、谭斌主编,案例6约瑟夫问题



我想先将代码写出来:

#include<stdio.h>#include<stdlib.h>int Joseph(int, int);//声明Joseph函数int main(void){     int N, M;    printf("\n请输入 游客数N and 报值数M :");    scanf("%d %d", &N, &M);    printf("\n优胜者编号:%d\n\n", Joseph(N, M));//运用Joseph函数    system("PAUSE");}int Joseph(int N, int M){    int i;    int j;//    int Count;//    int * Array;    //分配存储空间    Array = malloc(sizeof(int) * N);    //将所有游客赋值为1    for (i = 0; i < N; i++)        *(Array + i) = 1;    //算法核心    //死循环,i作为数组下标,j用来计数循环次数,Count也用来计数循环次数    for (i = 0, j = 0, Count = 0; 1; i++)    {        if (Count == M)//每当Count等于M的时候,代表一位游客将出列        {            Count = 0;//重置Count的值            *(Array + i - 1) = 0;//将出列游客赋值为0            j++;//统计有几位游客被赋值为0        }        if (j == N - 1) break;//当j==N-1时,只有一位游客值为1,可以跳出死循环了        if (i == N) i = 0;//重新“遍历”(检查)一次数组        if (*(Array + i) == 1) Count++;//检查游客,若值为1,Count++,若值为),Count不变    }    for (i = 0; i < N; i++)//找出Array[i]==1时的i的值    {        if (*(Array + i) == 1)//当Array[i]==1时,意味着获胜者编号为i+1,然后跳出循环        {            break;        }    }    //释放存储内存    free(Array);    //返回获胜者编号    return (i + 1);}

之所以写了“遍历”,一是应为我的思路就是不断的从Array[0]检查到Array[N-1],不断的Count++,j++;赋值为0代表着游客出列,直到只有一个游客值为0,找出他的编号再输出,解决方案;二是,“”,遍历好像经常用在二叉树上_(:з」∠)。



详解:(文笔练习中……)
我们从数组的第一位元素检查到最后一位,每当检查的游客值为1时,使Count++,这样,每当Count==报值数M时,就说明我们需要将此时Array[i]赋值为0,但我们要等到下一次迭代中才能将其赋值为0,而下一次迭代是的i值增加了1,所以,在代码中我们有Array[i-1]=0;代表着有一个游客出列,并且在该游客出列时,我们要重置Count的值,同时也要j++;
将出列游客赋值为0的目的是,当我们每次重新从第一位元素检查到最后一位时,对值为0的游客不计数,实现了用C语言描述出游客出列后的程序运行问题;
j++用来计数我们已经有多少个游客出列了,按题目要求,当出列人数为N-1时,我们中止循环;
然后通过检查数组中仅剩的值为1的编号,并返回该值,最后在main()函数中使用Joseph函数,解决约瑟夫问题。


结束语:
我想将自己的程序设计都记录下来,记录自己的进步,分享自己的编程思路,吸取、总结经验,不断完善。

原创粉丝点击