m个人围成一圈,1,2,3循环报数,报到3的人退出,并将退出的序号依次存到数组p中,包括最后一个人的序号。输出最后退出的是原来的第几号(最初的序号,以1起始)。若m=6,则最后退出的是1号,退出的顺序是 : 3 6 4 2 5 1;若m=10,则最后退出的是4号,退出顺序是: 3 6 9 2 7 1 8 5 10 4;若m=100,则最后退出的是91号,退出顺序是: 3 6 9……100 58 91。 编写函数int fun(int m ,int p[ ])实现上述功能,返回m个人中最后退出人的序号,并将退出的序号顺序写入p指向的数组中。在主函数中输入人数,调用fun后输出实参数组中保存的退出序号。每行输出10个数据。 本问题限定人数m不超过200人。
时间: 2023-06-10 18:07:09 浏览: 98
这道题可以用循环链表的思想来解决。具体做法如下:
1. 建立一个循环链表,链表中的每个节点代表一个人,并用一个整数变量num表示这个人报的数。
2. 从第一个人开始,每次找到报数为3的人并将其从链表中删除,同时将其编号存入数组p中。删除操作可以通过将该节点的前一个节点的next指针指向该节点的下一个节点来实现。
3. 重复执行步骤2,直到链表中只剩下一个节点为止。此时链表中仅剩的那个人即为最后退出的人。
4. 返回最后退出人的编号。
以下是代码实现:
```c++
#include <iostream>
using namespace std;
struct Node {
int num; // 人的编号
int count; // 报数
Node* next; // 指向下一个节点的指针
};
int fun(int m, int p[]) {
Node* head = new Node{1, 1, nullptr}; // 建立循环链表,第一个人编号为1,报数为1
Node* tail = head; // 尾指针指向第一个节点
for (int i = 2; i <= m; i++) { // 其他人的编号从2到m
tail->next = new Node{i, 1, nullptr}; // 将新创建的节点插入到链表尾部
tail = tail->next; // 尾指针指向新节点
}
tail->next = head; // 将链表头部和尾部相连,形成循环链表
int count = 1; // 从第一个人开始报数
Node* cur = head; // 当前节点指向第一个人
while (m > 1) { // 只要还有超过一个人在链表中,就继续循环
if (cur->count == 3) { // 如果当前节点的报数为3,则将其从链表中删除
p[m - 1] = cur->num; // 将删除的节点的编号存入数组p中
Node* prev = cur; // 找到当前节点的前一个节点
while (prev->next != cur) {
prev = prev->next;
}
prev->next = cur->next; // 将前一个节点的next指针指向当前节点的下一个节点
Node* temp = cur; // 删除当前节点
cur = cur->next;
delete temp;
m--; // 链表中节点数减1
}
else { // 如果当前节点的报数不为3,则继续报数
cur->count++;
count++;
cur = cur->next;
}
}
int result = cur->num; // 链表中仅剩的那个人即为最后退出的人
delete cur; // 释放内存
return result;
}
int main() {
int m;
cin >> m;
int p[200];
int result = fun(m, p);
for (int i = 0; i < m; i++) {
cout << p[i];
if ((i + 1) % 10 == 0 || i == m - 1) { // 每行输出10个数据
cout << endl;
}
else {
cout << " ";
}
}
cout << "最后退出的人的编号为:" << result << endl;
return 0;
}
```
阅读全文