#include<stdio.h>
#include<stdlib.h>
typedef struct Linklist
{
int data;
struct Linklist *next;
}List;
List *CreateHead()
{
List *headNode=(List *)malloc(sizeof(List));
headNode->data=-1;
headNode->next=NULL;
return headNode;
}
//List *NewNode(int data)
//{
// List *NewNode=(List *)malloc(sizeof(List));
// NewNode->data=data;
// NewNode->next=NULL;
// return NewNode;
//}
void Tail_insert(List *headNode,int n)
{
int i;
List *tail=headNode;
for(i=1;i<=n;i++)
{
// 建立循环的关键
List *NewNode=(List *)malloc(sizeof(List));
NewNode->data=i;
tail->next=NewNode;
NewNode->next=headNode->next;
tail=NewNode;
}
}
void Joseph(List *headNode,int n,int m)//n:表示从第几个开始数,m:表示数到几出去
{
List *Tail=headNode;
List *p=headNode->next;//先找从第几个开始数
while(p->data !=n)
{
p=p->next;
}
while(p->next !=p)
{
int i;
for(i=1; i<m; i++)
{
Tail=p;
p=p->next;
}
printf("出列的人是%d:\n",p->data);
Tail->next=p->next;//删除节点
free(p);
p=Tail->next;
}
printf("最后一个出列的人是%d:",p->data);
free(p);
}
void PrintfList(List *headNode)
{
List *pmove=headNode;
while(pmove->next !=NULL)
{
pmove=pmove->next;
printf("%d\n",pmove->data);
}
}
int main ()
{
int n,m,k;
List *List=CreateHead();
printf("请问你要录入多少个数:");
scanf("%d",&n);
printf("请问你要从第几个人开始数(0<m<=%d):",n);
scanf("%d",&m);
printf("请问要数到几出列:");
scanf("%d",&k);
Tail_insert(List,n);
Joseph(List,n,m);
return 0;
}
约瑟夫环难点
1.不知道如何建立一个循环链表
先建立头节点与新节点之间的联系让头指针指向第一个节点,让第一个节点的指针指向头指针指向的节点(第一个节点),让尾巴往后移一个位置,移到创造的节点位置,然后重新创造新的节点,让重新创造的节点的指针指向第一个节点,构成循环。
2.不知道如何清除,外加判断
1.首先得判断从编号几开始数,即正式开始数数 ,找到这个人的位置
2.数到几开始出去,利用循环判断,判断到几循环结束
为什么i要从1开始呢?因为本身到了的那个人就是第一个,相当于已经做了一次循环,列如我假设数到2出局,我本身已经数了1,再数一次就出局了,相当于再做一次循环。
tail所处的位置是删去节点的上一个位置,游戏结束是当最后一个人指向自己时游戏结束。
3.如何删去节点并重新开始循环
tail->next=p->next;
free(p);释放节点空间
p=tail-next (删除节点)
重新开始循环的条件
当判断结束,即使游戏已经结束判断出了获胜者。