题目分享:约瑟夫问题
让我们举个例子来看看
我们可以看到假设是报号为三的人走,那我们只要定义一个count 当他增长到三的时候,让此时循环到的人走,那我们是不是的需要一个指针进行循环呢,那我们还需要一个指针进行记录辅助这个遍历指针,否则,将这个指针指向的空间进行释放,那么就找不到链表了,所以我们移动一个位置,count就加一次,然后一前一后两个指针进行挪动。
1.我们首先得实现一个头尾相连的循环链表
我们之前学习单链表,所以这些代码对我们很好实现
typedef struct ListNode listnode;
listnode* chuang(int x)
{
listnode* newnode=(listnode*)malloc(sizeof(listnode));
if(newnode==NULL)
{
exit(1);
}
newnode->val=x;
newnode->next=NULL;
return newnode;
}
首先我们写一个为单独数据开辟空间的函数
listnode* list(int x)
{
listnode* head=chuang(1);
listnode* ps=head;
for(int i=2;i<=x;i++)
{
ps->next=chuang(i);
ps=ps->next;
}
ps->next=head;
return head;
}
我们再函数中实现对n个人的空间开辟,然后将这几个空间使用单链表的形式进行链接,最后返回头结点的指针。
接着我们是实现遍历次数符合则释放空间,剩下最后一个数据时候,在循环单链表中的特点是什么,那就它的尾结点的next指针指向的是自己的头结点。所以这个就是我们的循环遍历的终止条件。
int ysf(int n, int m ) {
listnode* head=list(n);
listnode* ps=head;
listnode* prev=NULL;
int count=1;
while(ps->next!=ps)
{
if(count==m)
{
prev->next=ps->next;
free(ps);
ps=prev->next;
count=1;//每次走掉一个人我们就需要把count重新定义成1,在进行次数的累计
}
else
{
prev=ps;
ps=ps->next;
count++;
}
}
return prev->val;
}
ok了