• C++
  • 约瑟夫问题 循环链表

  • @ 2025-7-3 22:09:10

这个程序模拟了约瑟夫问题的过程。简单来说,约瑟夫问题是这样的:有n个人围成一圈,从第一个人开始报数,报到k的人出列,然后从出列的下一个人重新开始报数,直到所有人都出列。程序会输出出列的顺序和最后剩下的人。

程序的核心是使用循环链表来表示围成一圈的人。每个节点代表一个人,包含一个编号和一个指向下一个人的指针。当一个人出列时,我们只需要调整指针,将他从链表中移除即可。

运行程序后,你可以输入总人数n和报数间隔k,程序会模拟整个淘汰过程并输出结果。这个程序适合中小学生理解链表结构和循环逻辑。

#include <iostream>
using namespace std;

// 定义链表节点结构
struct Node {
    int data;      // 节点存储的数据(人的编号)
    Node* next;    // 指向下一个节点的指针

    // 构造函数,初始化节点
    Node(int value) : data(value), next(nullptr) {}
};

// 创建循环链表
Node* createCircularList(int n) {
    if (n <= 0) return nullptr;

    // 创建第一个节点
    Node* head = new Node(1);
    Node* current = head;

    // 创建剩余的n-1个节点,并连接成环
    for (int i = 2; i <= n; ++i) {
        current->next = new Node(i);
        current = current->next;
    }

    // 最后一个节点指向头节点,形成环
    current->next = head;

    return head;
}

// 解决约瑟夫问题的函数
void josephusProblem(int n, int k) {
    if (n <= 0 || k <= 0) {
        cout << "参数必须为正整数!" << endl;
        return;
    }

    // 创建循环链表
    Node* head = createCircularList(n);
    Node* prev = nullptr;  // 当前节点的前一个节点
    Node* current = head;  // 当前节点,从第一个人开始

    cout << "出列顺序:";

    // 当链表中不止一个节点时,继续淘汰过程
    while (current->next != current) {
        // 找到第k个节点
        for (int i = 1; i < k; ++i) {
            prev = current;
            current = current->next;
        }

        // 输出被淘汰的人的编号
        cout << current->data << " ";

        // 删除当前节点
        prev->next = current->next;  // 跳过当前节点
        Node* temp = current;
        current = current->next;     // 移动到下一个节点
        delete temp;                 // 释放内存
    }

    // 输出最后剩下的人的编号
    cout << current->data << endl;
    cout << "最后剩下的人是:" << current->data << endl;

    // 释放最后一个节点的内存
    delete current;
}

int main() {
    int n, k;
    cout << "欢迎来到约瑟夫环问题模拟程序!" << endl;
    cout << "请输入总人数 n:";
    cin >> n;
    cout << "请输入报数间隔 k:";
    cin >> k;

    josephusProblem(n, k);

    return 0;
}

0 条评论

目前还没有评论...