解决约瑟夫环问题核心步骤:
1.建立具有n个节点、无头的循环链表
2.确定第一个报数人的位置
3.不断从链表中删除链节点,直到链表为空
#include <iostream> #include <stdio.h> #include <stdlib.h> using namespace std; typedef struct lnode { int data; struct lnode *link; }lnode; /** * @brief 约瑟夫环问题: * n 个人,编号为 1,2,...,n * 从编号K的人开报数(从1开始) * 喊道 m 的人出列,也就是:从 1 数到 m, * * @param total 总人数 * @param start 确定第一个开始报数的人编号 * @param outnum 指定出列者喊到的数 */ void JOSEPHUS(int total, int start, int outnum) { //1. 定义变量 lnode *p; lnode *r; lnode *curr; //curr 指向尾, curr->link 指向头 //2. 建立第一个节点 p = (lnode*)malloc(sizeof(lnode)); p->data = 1; p->link = p; curr = p; //3. 建立循环链表 for (int i=2; i<=total; i++) { lnode *t = (lnode*)malloc(sizeof(lnode)); t->data = i; t->link = curr->link; curr->link = t; curr = t; printf("%d ", i); } //4. 指针移动到第一个报数的人 while (start--) { r = p; p = p->link; } //5. 开始遍历删除 while (total--) { //定位删除点 for (int s=outnum-1; s--; r=p,p=p->link); printf("%d->", p->data); //删除节点 r->link = p->link; free(p); p = r->link; } printf(" "); } int main() { int total = 10; //总人数 int start = 1; //确定第一个开始报数的人编号(1,2,...) int outnum = 4; //指定出列者喊到的数 JOSEPHUS(total, start, outnum); }