约瑟夫环的问题可以分成四个部分:
1、一群人围在一起坐成环状 (建环)
2、从某个编号开始报规定的数 (找到相对应的数)
3、数到某个数的时候,此人出列 (删除找到的数)
4、一直循环,直到剩下最后一个人 (解环)
看代码:
#include<windows.h>
#include<stdio.h>
#include<assert.h>
typedef int DataType;
typedef struct Node
{
DataType data;
struct Node* next;
}Node, *pNode, List, *pList;
void InitLinkList(pList* pplist)//初始化
{
assert(*pplist != NULL);
*pplist = NULL;
}
pNode BuyNode(DataType d)
{
pNode p = malloc(sizeof(Node));
p->data = d;
p->next = NULL;
return p;
}
void PushBack(pList* pplist, DataType d)//尾插
{
assert(pplist != NULL);
pNode p = BuyNode(d);
if (*pplist == NULL)
{
*pplist = p;
}
else
{
pList cur = *pplist;
while (cur->next != NULL)
{
cur = cur->next;
}
cur->next = p;
}
}
void PrintLinkList(pList plist)//打印
{
while (plist != NULL)
{
printf("%d--->", plist->data);
plist = plist->next;
}
printf("over\n");
}
pNode JosephCircle(pList *plist, int k)
{
pList phead1 = *plist;
pList phead = *plist;
while (phead->next != NULL)
{
phead = phead->next;
}
phead->next = *plist;//建环
while (phead1->next != phead1)
{
int x = k - 1;
pList cur = phead1;
pList pre = NULL;
while (x)
{
pre = cur;
cur = cur->next;
x--;
}//找到相对应的数
pre->next = cur->next;//删除找到的数
phead1 = cur->next;//删除一个数后,下一个节点从1开始
free(cur);//删除后,需要释放
cur = NULL;
}
phead1->next = NULL;//解环
return phead1;
}
void test()
{
pList s;
InitLinkList(&s);
PushBack(&s, 1);
PushBack(&s, 2);
PushBack(&s, 3);
PushBack(&s, 4);
PushBack(&s, 5);
PushBack(&s, 6);
PushBack(&s, 7);
pList ret = JosephCircle(&s, 2);
PrintLinkList(ret);
}
int main()
{
test();
system("pause");
return 0;
}
重点:
1.报k时,引动k-1个单位,当移动第k-1个单位后,这是(k-1)--为0,这时就要将k重新定义为原来的值,方便下一次重新循环。
2.要将删除的那个节点的下一个节点改成下一次循环的第一个节点。
3.删除一个节点后一定要释放。
4.构成一个环最后需要解环。