约瑟夫退圈问题:利用循环链表类实现约瑟夫退圈问题:n 个人 (不同 id)围成一个圈,从 startId(任意数)个开始报数 m(任意数)个 数,数 m 的人出列排成新队列,m 清零,然后又从下一个人开始数 m 个数开始,数到 m 就出列接在新队列尾部,如此重复,直到所有 人都出列为止,请输出出列的次序(依次输出出列人员的编号)。 说明:参数n,stratId和m要通过输入确定,注意要考虑startId和m 大于n的情况
首先需要写个循环链表
#pragma once
#include<iostream>
using namespace std;
//结点类模板
template <class T>
class Node{
public:
T data;
Node<T>* next;
Node(T data) :data(data), next(nullptr) {};
};
#pragma once
#include "node.h"
template<class T>
class CircularList {
public:
Node<T>* head;
Node<T>* tail;
int size;
CircularList() { //循环链表初始化,尾指针置为空指针,头结点=尾结点
tail = nullptr;
head = tail;
size = 0;
}
void tailAdd(T data) { //尾插 头插在本问题中用不到,就不写了
Node<T>* p = new Node<T>(data);
if (tail == nullptr) { //如果尾指针为空,直接让尾指针=p
tail = p;
head = p;
}
else {
tail->next = p;
tail = p;
tail->next = head;
}
size++;
}
void remove(T data) { //根据数据删除结点
while (head->data == data) {
head = head->next;
size--;
if (size == 0)return;
}
Node<T>* p = head;
int i = 1;
while (p->next && i < size) {
if (p->next->data == data) {
if (p->next->next != nullptr)p->next = p->next->next;
else {
p->next = nullptr;
break;
}
size--;
}
p = p->next;
i++;
}
}
void printList() { //遍历链表打印
Node<T>* p = head;
int i = 0;
while (p && i < size) {
i++;
cout << p->data << endl;
p = p->next;
}
}
};
#include"circularList.h"
int main() {
CircularList<int> cl;
int n, startId, m;
cin >> n >> startId >> m;
if (startId > n || m > n) { //判断startId
cout << "输入错误!startId > n 或 m > n" << endl;
}
for (int i = 1; i <= n; i++) {
cl.tailAdd(i); //插入编号
}
Node<int>* p = cl.head;
int i = 0;
while (i < startId - 1) { //找到开始位置
i++;
p = p->next;
}
i = 1; //i记录数到了几
int j = 0; //j记录已经出列几位
while (p && j < n) {
if (i == m) {
cout << p->data << endl; //输出编号
cl.remove(p->data); //退出链表
j++;
i = 0;
}
i++;
p = p->next;
}
cout << "已全部出列" << endl;
return 0;
}