/*
*
* 播布客教学视频_C学习笔记_10.2_约瑟夫环问题(数组链表)
* author: syt<sytshanli@163.com>
* create date: 2014.11.29
*
* 1.如何跳过无效比较呢?
* 2.通过数组实现链表管理,
* 利用一个数组记录每个元素的下一个位置(跳过无效的位置)
* 1 2 3 4 5 6下标依次为1 2 3 4 5 0
* 3.最后调试得到,其实只是需要next数组,与peopel[]有关的都注释掉
*
*/
#include<stdio.h>
#define ALL 6 //all people in the ring
#define out 3 //if counter to 3,than out
/* global array for all people in the ring */
int people[ALL];
/* 记住下一个人的下标*/
int next[ALL];
/*init ring*/
void init_ring(void)
{
int i = 0;
//for(i = 0;i < ALL;i++)
// people[i] = i +1;
for(i = 0;i < ALL;i++)
next[i] = (i + 1) % ALL;
}
/*print ring*/
void print_ring(void)
{
int i = 0;
//for(i = 0;i < ALL;i++)
// printf("%d ",people[i]);
printf(" (people)\n");
for(i = 0;i < ALL;i++)
printf("%d ",next[i]);
printf(" (next)\n");
}
int main(void)
{
int left; //环中有多少人
int counter;
int i;
int prev;
printf("demo josphus ring problem\n");
init_ring( );
print_ring( );
left = ALL; //left = all people
counter = 0; //counter = 1,2,3
i = 0; //代表从0开始
prev = ALL - 1; //0的前面一个人应该是5
while(left > 1)
{
/* if(????) */
//if(people[i] > 0) //如果这个人没走,那么就要计数,一旦出局了,那么赋值0
counter++; //报数的加法操作(条件呢??)
/* if(????)
一定是有人离开了才会有left减少,
什么情况下会有人离开呢,
*/
if(counter == out) //那就是报到m
{
left--; //什么情况下会少人呢
printf("%d is out\n",i + 1);//谁出局了
//print_ring( ); //每次有人出局就打印环
//people[i] = 0; //出局后位置为0
/*设置next数组,给它前面的一个人*/
next[prev] = next[i];//可能出现bug的地方
print_ring( ); //每次有人出局就打印环
counter = 0; //必须重新计数(bug)
}
//调试信息
//printf("i = %d ,counter = %d ,left = %d\n",i,counter,left);
//print_ring( );
//if(left < 1) //什么情况下会推出呢?
// break;
prev = i;
i = next[i]; //可能数组越界
getchar( ); //每次回车后才继续
}
printf("问题解决了!");
/*
//init ring
for(i = 0;i < ALL;i++)
people[i] = i +1;
//print ring
for(i = 0;i < ALL;i++)
printf("%d ",people[i]);
printf("\n");
*/
return 0;
}