思路:
我们要创建两个指针
有一个指针pcur指向头结点,该pcur作为报数的指针,还有一个指针ptail指向尾结点,作为记录pcur的地址
每报数为m时,pcur指向下一个元素的地址,ptail销毁报数为m的地址,然后ptail指向pcur,继续重新报数
最后当只剩一个元素时,即pcur->next==pcur,退出循环
答案:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
typedef struct ListNode {int val;struct ListNode* next;
}ListNode;
ListNode* buyNode(int x) //申请一个新结点
{ListNode* node = (ListNode*)malloc(sizeof(ListNode));if (node == NULL) //如果开辟空间失败{perror("malloc fail!");exit(1);}node->val = x;node->next = NULL;return node;
}
ListNode* creatCircle(int n) //创建循环链表
{ListNode* phead = buyNode(1); //创建第一个结点ListNode* ptail = phead; for (int i = 2; i <= n; i++) //创建n-1个结点{ptail->next = buyNode(i);ptail = ptail->next;}ptail->next = phead; //首尾相连return ptail;
}
void ysf(int n, int m) //约瑟夫函数
{ListNode* prev = creatCircle(n); //尾结点ListNode* pcur = prev->next; //头结点int count = 1;while (pcur->next != pcur) //如果剩余人数大于1{if (count == m) //如果已经有m次报数了{printf("%d->", pcur->val); //打印出圈人员prev->next = pcur->next; //让前一个结点直接链接下一个结点free(pcur); //销毁空间pcur = prev->next; //报数从下一个结点开始count = 1; //报数次数回到1}else //没到m次报数{prev = pcur; //往前移动一位pcur = pcur->next; //往前移动一位count++; //计数器加1}}printf("%d", pcur->val); //打印最后一个出圈人员free(pcur); //销毁空间
}
int main()
{int n = 0, m = 0;printf("请输入n和m的值:\n");scanf("%d%d", &n, &m);ysf(n, m);return 0;
}