约瑟夫问题(约瑟夫环):M个人围成圈(编号1到M),从第一个人开始报数,报数为N(N<M)的这个人退出,然后下一个人重新按1开始报数,第N个人退出,按照这个规则不断循环,直到剩下最后一个人为止,最终剩下的这个人胜出,要给出他的编号。
问题求解:可以将循环链表类比到这个场景,通过配合索引值的遍历来解决:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"Circle_LinkList.h"
#define M 8
#define N 3
typedef struct MYNUM
{
CircleLinkNode node;
int val;
}myNum;
void myPrint(CircleLinkNode* data)
{
myNum* mynum = (myNum*)data;
printf("%d ", mynum->val);;
}
int myCompare(CircleLinkNode* data1, CircleLinkNode* data2)
{
myNum* num1 = (myNum*)data1;
myNum* num2 = (myNum*)data2;
if (num1->val == num2->val)
{
return CIRCLELINKLIST_TRUE;
}
return CIRCLELINKLIST_FALSE;
}
int main()
{
//创建循环链表
CircleLinkList* clist = Init_CircleLinkList();
//链表插入数据
myNum num[M];
for (int i = 0; i < 8; i++)
{
num[i].val = i + 1;
Insert_CircleLinkList(clist, i, (CircleLinkNode*)&num[i]);
}
//打印
Print_CircleLinkList(clist, myPrint);
printf("\n");
int index = 1;
//辅助指针
CircleLinkNode* pCurrent = clist->head.next;//index对应第一个人
while (Size_CircleLinkList(clist) > 1)
{
if (index == N)
{
myNum* tempNum = (myNum*)pCurrent;
printf("%d ", tempNum->val);
//缓存待删除结点的下一个结点
CircleLinkNode* pNext = pCurrent->next;
//根据值删除
RemoveByValue_CircleLinkList(clist, pCurrent, myCompare);
pCurrent = pNext;
if (pCurrent == &(clist->head))
{
pCurrent = pCurrent->next;
}
index = 1;
}
index++;
pCurrent = pCurrent->next;
if (pCurrent == &(clist->head))
{
pCurrent = pCurrent->next;
}
}
if (Size_CircleLinkList(clist) == 1)
{
myNum* tempNum = (myNum*)Front_CircleLinkList(clist);
printf("%d\n", tempNum->val);
}
else
{
printf("出错\n");
}
//释放链表内存
FreeSpace_CircleLinkList(clist);
system("pause");
return 0;
}
测试结果: