【数据结构与算法设计(C描述)】北京理工大学实验:单向环表实现约瑟夫环

实验要求

采用单向环表实现约瑟夫环。

请按以下要求编程实现:

(1)从键盘输入整数m,通过create函数生成一个具有m个结点的单向环表。环表中的结点编号依次为1,2,……,m。

(2)从键盘输入整数s(1<=s<=m)和n,从环表的第s个结点开始计数为1,当计数到第n个结点时,输出该第n结点对应的编号,将该结点从环表中消除,从输出结点的下一个结点开始重新计数到n,这样,不断进行计数,不断进行输出,直到输出了这个环表的全部结点为止。

例如,m=10,s=3,n=4。则输出序列为:6,10,4,9,5,2,1,3,8,7。

1.需求分析

    本程序的任务是使用单向环表实现约瑟夫环。用户输入整数 m(节点数目),然后根据约瑟夫环规则,从给定的起始位置 s 和计数间隔 n 开始,输出序列并消除节点,直到所有节点都被输出。

2.概要设计

(1)抽象数据类型的定义

Node 结构体:表示环形链表的节点,包含数据成员 data(节点编号)和 next(指向下一个节点的指针)。

(2)主程序流程

① 输入节点数目 m、起始位置 s、计数间隔 n。

② 创建环形链表。

③ 执行约瑟夫环操作,输出符合规则的节点编号序列。

3.详细设计

(1)create 函数

根据输入的节点数目 m 创建一个具有 m 个节点的环形链表。

(2)josephus 函数

① 根据起始位置 s 和计数间隔 n,执行约瑟夫环操作。

② 遍历链表,找到指定位置的起始节点。

③ 循环输出满足条件的节点编号,删除节点并调整链表直至所有节点被输出。

4. 调试分析

在调试过程中,可能会遇到以下问题:

(1)节点删除及链表指针操作的正确性:确保节点的删除与链表指针的调整没有错误,避免出现内存泄漏或链表指针混乱的情况。

(2)计数规则和节点删除顺序:验证程序实现的约瑟夫环是否按照预期规则进行计数和节点删除。

5. 测试结果

使用 m=10、s=3、n=4 这组测试用例进行测试,预期输出序列为:6,10,4,9,5,2,1,3,8,7。测试结果应该与预期一致。

 6.完整代码

#include <iostream>

//定义单向环形链表的节点结构
struct Node {
    int data;//节点数据,这里表示节点编号
    Node* next;//指向下一个节点的指针
    Node(int value) : data(value), next(nullptr) {}//节点结构体构造函数
};

//创建单向环形链表
Node* create(int m) {
    if (m <= 0) {
        return nullptr;
    }

//创建链表头节点
    Node* head = new Node(1);
    Node* current = head;

//依次创建 m-1 个节点,构成环形链表
    for (int i = 2; i <= m; ++i) {
        current->next = new Node(i);
        current = current->next;
    }

    current->next = head;//将链表闭合成环形

    return head;//将链表闭合成环形
}

//执行约瑟夫环操作
void josephus(int m, int s, int n) {
    if (m <= 0 || s <= 0 || s > m || n <= 0) {
        std::cout << "输入无效!" << std::endl;
        return;
    }

    Node* head = create(m);//创建具有 m 个节点的环形链表
    Node* current = head;
    Node* prev = nullptr;

//创建具有 m 个节点的环形链表
    for (int i = 1; i < s; ++i) {
        prev = current;
        current = current->next;
    }

    std::cout << "约瑟夫环输出序列为:";

    while (m > 0) {
        for (int i = 1; i < n; ++i) {
            prev = current;
            current = current->next;
        }

        std::cout << current->data << " ";//输出节点编号

//删除当前节点并调整链表
        if (current == head) {
            head = head->next;
        }
        prev->next = current->next;
        delete current;
        current = prev->next;

        --m;//减少链表节点数目
    }

    std::cout << std::endl;
}

int main() {
    int m, s, n;
    std::cout << "输入节点数目 (m):";
    std::cin >> m;

    std::cout << "输入起始位置 (s):";
    std::cin >> s;

    std::cout << "输入计数间隔 (n):";
    std::cin >> n;

    josephus(m, s, n);

    return 0;
}

***本实验报告属原创,各位可以免费取用,严禁商用

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值