以下是顶嵌嵌入式培训学员徐凯所写的C语言技术文章:
约瑟夫问题:N个人围成一圈,从第M个位置开始按1.2.3...报数报到K的就出圈,请问出圈的人的顺序.请用链表实现该功能。约瑟夫问题可以用循环单链表解决,循环单链表的特点是链表中最后一个节点的指针域不再是NULL,而是指向整个链表的第一个节点,从而使链表形成一个环。
本题用到链表的建立,删除链表中的节点等知识:
#include
#include
#define NULL 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef struct Cnode
{ int ID;
struct Cnode *next;
}CNode;
CNode
*joseph;
int Create_clist(CNode *clist,int
n) //创建含n个节点的循环单链表
{ CNode
*p,*q;
int i;
clist=NULL;
for(i=n;i>=1;i--)
{ p=(CNode *)malloc(sizeof(CNode));
if(p==NULL)
return OVERFLOW;
p->ID=i;
p->next=clist;
clist=p;
if(i==n)
q=p;
}
q->next=clist;
joseph=clist;
return OK;
}
int Josephus(CNode *clist,int
m,int n,int k)
{ int
i;
CNode *p,*q;
if(m>n) return
ERROR;
if(!Create_clist(clist,n))
return
ERROR;
p=joseph;
for(i=1;i
p=p->next;
while(p)
{ for(i=1;i
p=p->next;
q=p->next;
printf("%d ",q->data);
if(p->next==p)
p=NULL;
else { p->next=q->next;
p=p->next;
free(q);
}
}
clist=NULL;
}
void main( )
{ int m,n,k,i;
CNode
*clist;
clist=NULL;
printf("\n请输入围坐在圆桌周围的人数n:");
scanf("%d",&n);
printf("\n请输入第一次开始报数人的位置m:");
scanf("%d",&m);
printf("\n你希望报数到第几个数的人出列?");
scanf("%d",&k);
Create_clist(clist,n);
printf("\n出列的顺序如下:\n");
Joseph(clist,m,n,k);
getch();
}