约瑟夫环是一个经典的数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
解决这种问题的方法很多,有利用数学的归纳法解决的,不过这种方法实现的代码我没耐心看下去,而且这种方式不能模拟过程,只能告诉你最后出队的元素的值;还有一种方法是利用循环列表来模拟实现整个过程,而且思路清晰,实现起来也很简单,下面我贴出利用循环列表解决约瑟夫环的C代码:
/*
Code By Lucifa 2012/09/18
*/
#include <stdio.h>
#include <stdlib.h>
/* 构建环节点结构体和其指针结构*/
typedef struct _RingNode
{
int pos;
struct _RingNode *Next;
}RingNode,*RingNodePtr;
/* 构建瑟夫环 */
void CreatRing (RingNodePtr pHead ,int count)
{
RingNodePtr pCurr=NULL,pPrev=NULL;
int i=1;
pPrev=pHead;
while(--count>0)
{
pCurr = (RingNodePtr)malloc(sizeof(RingNode));
i++;
pCurr->pos=i;
pPrev->Next=pCurr;
pPrev = pCurr;
}
pCurr->Next = pHead;//构成环形链表
}
/* 获取第K个位置的节点的地址 */
RingNodePtr GetK(RingNodePtr pHead,int K)
{
int i=1;
RingNodePtr pCurr=NULL;
pCurr=pHead;
while(i<K)
{
pCurr=pCurr->Next;
i++;
}
if(i==K)
{
return pCurr;
}
else
{
return NULL;
}
}
/* 打印当前瑟夫环 */
void PrintRing(RingNodePtr pHead)
{
RingNodePtr pCurr=NULL;
pCurr=pHead;
printf("%d", pCurr->pos);
pCurr = pCurr->Next;
while(pCurr!=pHead)
{
printf(" ->%d", pCurr->pos);
pCurr = pCurr->Next;
}
}
/* 节点依次按步长 m 出队,并打印 */
void KickFromRing(RingNodePtr pHead, int m)
{
RingNodePtr pCurr, pPrev;//当前节点指针 pCurr ,当前节点的前驱指针pPrev
int i = 1; // 计数
pCurr = pPrev = pHead;
if(m==1)
{
printf("\n%d",pCurr->pos);
pCurr=pCurr->Next;
while(pCurr!=pPrev)
{
printf("\n%d",pCurr->pos);
pCurr=pCurr->Next;
}
}
else
{
while(pCurr != NULL)
{
if (i == m)
{
// 踢出环
printf("\n%d", pCurr->pos); // 显示出圈循序
pPrev->Next = pCurr->Next;
free(pCurr);
pCurr = pPrev->Next;
i = 1;//重新置位计步器
}
pPrev = pCurr;
pCurr = pCurr->Next;
i++;//记已走步长
if(pPrev == pCurr)
{
// 最后一个节点
printf("\n%d", pCurr->pos); // 显示出圈循序
free(pCurr);
break;
}
}
}
}
int main()
{
int m = 0, n = 0,k=0;
RingNodePtr pHead = NULL;
printf("---------------Josephus Ring---------------\n");
printf("N(person count) = ");
scanf("%d", &n);
printf("M(out number) = ");
scanf("%d", &m);
printf("K(start position) = ");
scanf("%d", &k);
if(n <= 0 || m <= 0)//判断人数和步长的输入是否合法
{
printf("Input Error\n");
system("pause");
return 0;
}
if(k>n)
{
printf("Start Position Input Error\n");
system("pause");
return 0;
}
// 建立链表
pHead = (RingNodePtr)malloc(sizeof(RingNode));//建立头节点
pHead->pos = 1;
pHead->Next = NULL;
CreatRing(pHead, n);
//打印初始化链表
printf("The Created List is :");
PrintRing(pHead);
//获取起始位置K的地址
pHead= GetK(pHead,k);
if(pHead!=NULL)//成功获取位置K的地址
{
// 开始出圈
printf("\nKick Order: ");
KickFromRing(pHead, m);
printf("\n");
}
system("pause");
return 0;
}