/******************************************************************************
FILENAME: Josephus.c
DESCRIPTION: 一个经典的循环计数问题,由于它的本身特点所以采用循环形式的数据
结构,这里采用循环链表。由于头节点主要标记链表开始,而在循环链表
中更适合用头指针。输入圈数大小然后是间隔,然后程序将给出杀人顺序
和坐落位置指针。
header stdio.h/malloc.h
data types:_int
local function declaration:
main
AUTHOR: qiuyatao
CREATED ON: 14-10-2009
REVISION HISTORY:
18-10-2009 第二次修正
20-10-2009 第三次修改
******************************************************************************/
/*****************************************************************************
Header files are included below
*/
#include <stdio.h>
#include <malloc.h>
/******************************************************************************
Data types are defined below
*/
typedef struct personNode
{
int signal;
int next;
} PersonNode;
/******************************************************************************
Local functions are declared below
*/
int Josephus_elim (PersonNode *p, int span);
int Josephus (int total, int span);
/******************************************************************************
Josephus_elim ()
Description:Josephus问题的关键环节,淘汰不需要的元素。通过循环计数找到相应
间隔的位置执行删除节点操作,删除节点只是通过将节点后继索引标记为它本身的数值
,循环进行一直到剩下最后一个节点。
Inputs:number,span
Returns:position
*/
int Josephus_elim ( PersonNode *p, int span )
{
int pre,now,count=0;//两个个索引标记 和一个计数器
pre = now = 0;
while(p[now].next != now)//结束条件是剩下一个节点,即p[now].next == now ;
{
count++;//循环计数
if(span+1 == count)
{ //杀人!
printf("the %d person dead!/nit's position is %d/n",p[now].signal,&p[now]);
p[pre].next = p[now].next;
p[now].next = now;//删除节点
pre = now = p[pre].next;
count = 0;//回复计数器
}
else
{
pre = now;
now = p[now].next;//继续向下进行查找
}
}
return p[now].signal;//返回剩下的节点值
}
/******************************************************************************
insert_sort () - sorting an array with insertion sort algorithm
Description:
Inputs:
Returns:
*/
int Josephus ( int total, int span )
{
int i,result;//申请内存空间
PersonNode *p = (PersonNode *)malloc(sizeof(PersonNode)*total);
if(p==0)
{ //申请失败,停止运行
printf("no enough room!/n");
exit(0);
}
for(i=0;i<total-1;i++)//循环建立链表
{
p[i].signal = i+1;
p[i].next = i+1;
}
p[i].next = 0;//将最后一个节点循环执行第一个节点
p[i].signal = i+1;
result = Josephus_elim( p, span );
free(p);//释放申请的内存
return result;
}
/******************************************************************************
*/
int main()
{ //测试程序执行
int number,span,rs;
while(1)
{
printf("please input the number in the loop:/n");
scanf("%d",&number);
printf("please input the span in the elimination:/n");
scanf("%d",&span);
rs = Josephus(number, span);
printf("the only one who living is %d/n",rs);
}
system("pause");
}
//需要记录一下是因为自己曾经在这里,在一个节点删除后没有做好标记,结果死循环,cpu50%内存180m。所以指针操作还是要小心啊!
//还有就是对于大内存分配使用malloc时候一定不能忘记了要做检测!