C++ 实现约瑟夫环问题:代码解析与新手常见错误
C++ 实现约瑟夫环问题:代码解析与新手常见错误
#include<iostream>
using namespace std;
// 定义节点类
class Node {
public:
int data;
Node* next;
Node(int d = 0, Node* n = NULL) :data(d), next(n) {}
// 定义了一个构造函数,用于创建节点对象。其中,`d` 表示节点中存储的数据,`n` 表示指向下一个节点的指针。
// 默认值为 `0` 和 `NULL`。`data(d)` 和 `next(n)` 表示将 `d` 和 `n` 分别赋值给 `data` 和 `next` 成员变量。
};
// 定义约瑟夫环类
class Joseph {
private:
Node* head;
// 头节点
int n, m;
// 人数和步长
public:
Joseph(int num, int step) :n(num), m(step) {
head = new Node(1);
// 创建头节点
Node* p = head;
// 指向头节点的指针
for (int i = 2; i <= n; i++) {
// 创建其他节点
p->next = new Node(i);
p = p->next;
}
p->next = head;
// 将最后一个节点指向头节点,形成环
}
void run() {
Node* p = head;
// 指向头节点的指针
while (p->next != p) {
// 当只剩一个节点时结束循环
for (int i = 1; i < m - 1; i++) {
// 找到要删除的节点的前一个节点
p = p->next;
}
cout << p->next->data << ' ';
// 输出要删除的节点的数据
Node* temp = p->next;
// 将要删除的节点保存到临时指针中
p->next = temp->next;
// 将要删除的节点从链表中删除
delete temp;
// 释放内存
p = p->next;
// 指向下一个节点
}
cout << p->data << endl;
// 输出最后剩下的节点的数据
}
};
int main() {
int n, m;
cout << "请输入人数n和步长m:";
cin >> n >> m;
Joseph joseph(n, m);
// 创建约瑟夫环对象
joseph.run();
// 运行约瑟夫环
return 0;
}
分析一下这个代码中新手最容易犯错的代码是哪里,然后一般能从修正错误中学到什么内容:
可能存在的错误:
- 没有正确初始化变量 n 和 m,导致程序出现未定义的行为。
- 约瑟夫环的步长 m 可能大于人数 n,这会导致程序出现数组越界等错误。
- 约瑟夫环的步长 m 可能等于 1,这会导致程序进入死循环。
- 在创建节点对象时,没有正确赋值 next 指针,可能导致链表出现断裂。
- 在删除节点时,没有正确释放内存,可能导致内存泄漏。
- 在找到要删除的节点的前一个节点时,可能会越过环的起点,导致程序进入死循环。
修正错误后,我们能够学到:
- 变量初始化是编写程序时必须注意的一个细节,特别是在使用动态内存分配时更需要注意。
- 对于算法的特殊情况,需要特别考虑和处理,以避免出现不必要的错误。
- 在创建和操作链表时,需要特别注意指针的正确赋值和处理。
- 在使用动态内存分配时,需要正确释放内存,以避免出现内存泄漏等问题。
- 在进行循环时,需要特别注意循环边界和终止条件,以避免进入死循环。
原文地址: https://www.cveoy.top/t/topic/mTlk 著作权归作者所有。请勿转载和采集!