【数据结构与算法】约瑟夫环(C/C++)

news2024/11/16 21:28:23

实践要求

1. 问题描述

约瑟夫问题的一种描述是:编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始。按顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。试设计程序求出出列顺序。


2. 基本要求

利用单向循环链表存储结构模拟此过程,按照出列的顺序印出个人的编号。


3. 测试数据

3.1 input

  • m = 20
  • n=7
  • 7个人的密码分别为:3,1,7,2,4,8,4

3.2 output

(正确的结果应为6,1,4,7,2,3,5)


实践报告

1. 题目分析

说明程序设计的任务,强调的是程序要做什么,此外列出各成员分工

程序设计任务:解决约瑟夫问题——编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始。按顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。最后输出列顺序。


2. 数据结构设计

说明程序用到的数据结构的定义,主程序的流程及各模块之间的层次关系

使用了单向循环链表。定义了一个Person的类(包含了密码(code)、编号(No)、下一个人的指针 Person* next、以及一个构造函数Person(int c, int N) 其中"c"表示当前人的code,"N"表示当前人的编号 )

主程序流程图

在这里插入图片描述


3. 程序设计

实现概要设计中的数据类型,对主程序、模块及主要操作写出伪代码,画出函数的调用关系

数据类型

  • vector数组
  • 指针
  • int

主程序操作伪代码

在这里插入图片描述


4. 调试分析

程序复杂度分析

1. 空间复杂度
o ( n ) o(n) o(n)
2. 时间复杂度
O ( m + n + ∑ c o d e ) O(m+n+\sum code) O(m+n+code)

心得体会

使用链表要注意不能使用空指针,不能使用指向未知内存的指针,以及用完指针后要及时释放。否则就会碰到一些莫名其妙的错误。


5. 测试结果

列出测试结果,包括输入和输出

测试结果一

input

上限值为20、人数为7、每人的密码分别为3、1、7、2、4、8、4

output

6,1,4,7,2,3,5

在这里插入图片描述

测试结果二

input

上限值为30、人数为7、每人的密码分别为3、1、7、2、4、8、4

output

2,3,5,4,7,6,1

在这里插入图片描述


6. 用户使用说明

给出主界面及主要功能界面

主界面

在这里插入图片描述

使用说明

输入上限值后回车 -> 输入人数后回车 -> 输入每个人的密码后回车 -> 全部密码输入完毕后自动打印出列人员的编号。

7. 附录

源程序文件清单:
JosephusProblem.cpp //主程序

8. 全部代码

/*问题描述
约瑟夫问题的一种描述是:编号为1,2,...,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始。按顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。试设计程序求出出列顺序。
基本要求
利用单向循环链表存储结构模拟此过程,按照出列的顺序印出个人的编号。
测试数据
m的初值为20;n=7,7个人的密码: 3,1,7,2,4,8,4。(正确的结果应为6,1,4,7,2,3,5) 
(报告上要求写出多批数据测试结果
实现提示
程序运行后首先要求用户指定初始报数上限值与人数,然后读取各人的密码*/

#include <iostream>
#include <vector>
using namespace std;

//人类
class Person {
public:
    //密码
    int code;
    //编号
    int No;
    //下一个人的指针
    Person *next = nullptr;
    //构造函数
    Person(int c, int N):code(c), No(N) {
        
    }
};

int main() {
    //下一次要走的步数
    int step;
    //有多少个人
    int num;
    cout << "请输入报数上限值" ;
    cin >> step;
    cout << "请输入总共有多少个人";
    cin >> num;

    //head存循环单链表的头,即编号为1的人的位置;tmp为临时变量,但最后它将存放最后一个人的位置
    Person *head, *tmp;
    //构造循环单链表,这是一个没有头节点的循环单链表
    for(int i = 0; i < num; ++i) {
        int code;
        //读取密码
        printf("请输入第%d个人的密码",i + 1); 
        cin >> code;
        if(i == 0) {
            //head,即第一个人的位置
            head = new Person(code, i + 1);
            tmp = head;
        }else {
            tmp->next = new Person(code, i + 1);
            //更新
            tmp = tmp->next;
        }
    }
    //将尾衔接到头上
    tmp->next = head;

    //start每一次报数开始的位置,随着每个人报数一步步移动
    Person *start = head;
    //前驱指针
    Person *pre = tmp;
    //存放最终结果的序号列表
    vector<int> NoList;
    for(int i = 0; i < num; ++i) {//num次循环,即num次报数
        for(int j = 0; j < step - 1; ++j) {
            //前驱结点更新
            pre = start;
            //随着报数进行,一步步指向下一个人
            start = start->next;
        }//循环结束,指到的人便出列
        //读取密码
        step = start->code;
        //存入序号
        NoList.push_back(start->No);
        //记录一下下一个结点的位置,方便删除此结点,即指到的人出列
        Person *newStart = start->next;
        //删除结点
        pre->next = start->next;
        //释放空间
        delete start;
        //更新
        start = newStart;
    }
    //输出结果
    for(auto i : NoList) {
        cout << i << ' ';
    }
    return 0;
}


结束语

  因为是算法小菜,所以提供的方法和思路可能不是很好,请多多包涵~如果有疑问欢迎大家留言讨论,你如果觉得这篇文章对你有帮助可以给我一个免费的赞吗?我们之间的交流是我最大的动力!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/707579.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

docker镜像fauria/vsftpd dockerfile解析(ENV命令,**占位符**)dockerfile命令、dockerfile指令

文章目录 fauria/vsftpddockerfile原始文件dockerfile解析 fauria/vsftpd fauria/vsftpd是一个由Docker Hub用户"fauria"创建的Docker镜像。这个镜像是基于CentOS 7构建的&#xff0c;包含了vsftpd&#xff08;Very Secure FTP Daemon&#xff09;服务&#xff0c;并…

NASA网站曝严重漏洞,或将沦为黑客钓鱼网站?

美国国家航空航天局&#xff08;NASA&#xff09;天体生物学专用网站存在一个严重的安全漏洞&#xff0c;可能通过伪装带有NASA名称的危险URL来诱骗用户访问恶意网站。 太空旅行无疑是危险的。然而&#xff0c;在访问NASA网站的时候也有可能如此。Cybernews研究团队发现了一个N…

Scala之泛型详解

泛型用于指定类或方法可以接受任意类型参数&#xff0c;参数在实际使用时才被确定&#xff0c;泛型可以有效地增强程序的适用性&#xff0c;使用泛型可以使得类或方法具有更强的通用性。泛型的典型应用场景是集合及集合中的方法参数&#xff0c;可以说同 Java 一样&#xff0c;…

基于粒子群算法的无约束优化问题求解

基于粒子群算法的无约束优化问题求解 1 引言2 粒子群算法2.1 粒子群优化原理2.2 粒子群算法寻优策略与参数控制粒子群算法流程 3 粒子群算法求解无约束优化问题3.1 粒子群算法求解Sphere函数&#xff08;单峰测试函数&#xff09;3.2 Schwefels Problem 2.26&#xff08;多峰测…

chatgpt赋能python:Win7怎么安装Python?

Win7怎么安装Python&#xff1f; 如果你正在使用Windows 7操作系统&#xff0c;想要安装Python&#xff0c;那么你来对了地方。Python是一种利用广泛的编程语言&#xff0c;可用于开发Web应用程序、数据分析和科学计算、机器学习等各种领域。 在此篇文章中&#xff0c;我们会…

MATLAB matlab人脸识别源码+使用说明+操作说明内容清晰适合新手

程序运行界面&#xff1a; 部分代码&#xff1a; function varargout facerecg(varargin) % FACERECG MATLAB code for facerecg.fig % FACERECG, by itself, creates a new FACERECG or raises the existing % singleton*. % % H FACERECG returns the hand…

Revit中如何导入、导出明细表?

Revit中明细表的作用非常大&#xff0c;项目中的数据归类整理及统计都离不开它&#xff0c;今天给大家分享一下如何在Revit中进行明细表标准的导出及导入&#xff0c;减少在实际项目中的重复性工作。 1、首先在Revit中新建一个项目文件&#xff0c;在平面视图中随便画几条管道…

用git下载gitee上的项目资源

目录 用git下载gitee上的项目资源 用git 的clone 命令 然后到gitee上复制相关的下载地址&#xff1a; 粘贴到clone后面即可&#xff08;注意地址与clone之间有空格&#xff01;&#xff01;&#xff01;&#xff09; 运行结果&#xff1a; 用git下载gitee上的项目资源 用git…

学习vue2笔记

学习vue2笔记 文章目录 学习vue2笔记脚手架文件结构关于不同版本的Vuevue.config.js配置文件ref属性props配置项mixin(混入)插件scoped样式总结TodoList案例webStorage组件的自定义事件全局事件总线&#xff08;GlobalEventBus&#xff09;消息订阅与发布&#xff08;pubsub&am…

LeetCoda 打卡day53--动态规划之最长子序列

一个人的朝圣 — LeetCode打卡第52天 知识总结 Leetcode 1143. 最长公共子序列题目说明代码说明 Leetcode 53. 最大子数组和题目说明代码说明 Leetcode 1035. 不相交的线题目说明代码说明 知识总结 今天几道最长子序列的题目, 都可以用一个固定的模版完成. 理解其中递推公式的…

字典序最小回文串

字典序最小回文串 题目解读 给你一个由 小写英文字母 组成的字符串 s &#xff0c;你可以对其执行一些操作。在一步操作中&#xff0c;你可以用其他小写英文字母 替换 s 中的一个字符。 请你执行 尽可能少的操作 &#xff0c;使 s 变成一个 回文串 。如果执行 最少 操作次数…

DAY38——动态规划

步骤&#xff1a; 确定dp数组&#xff08;dp table&#xff09;以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组 题目一. 斐波那契数列 1. 确定dp数组以及下标的含义 dp[i]的定义为&#xff1a;第i个数的斐波那契数值是dp[i] 2. 确定递推公式 状态…

FFmpegFrameGrabber视频抽帧工具类

Bytedeco 通过视频链接进行关键帧抽取图片&#xff0c;利用FFmpegFrameGrabber对视频流进行抽帧处理。 一、引入POM依赖 <dependency><groupId>org.bytedeco</groupId><artifactId>javacv</artifactId><version>1.4.1</version><…

TCP 拥塞状态机演进

下面是 TCP 拥塞状态机&#xff1a; 但它只是冰山一角&#xff0c;这只是 loss-based 状态机&#xff0c;实现一个完全的 delay-based cc 就对不上这个状态机。 该状态机来自 RFC5681&#xff0c;源自 RFC2581&#xff0c;RFC2001&#xff0c;大概在 1990 年代&#xff0c;l…

10分钟内创意爆发,这些头脑风暴技巧让你IDEA满满

当初道叔刚入广告行业&#xff0c;与同事经历了一次困扰的头脑风暴&#xff0c;老板让他们想出一个大集团公司年会的主题口号。我们7-8个团队成员耗费了一个下午的时间&#xff0c;提出了几十个提议&#xff0c;但最终硬是没有一个能满足需求。许多人可能也有过道叔这样的经历。…

Js保留树型数据指定层级

自定义一个树型的数据 const tree [{value: 1, label: "1",children: [{value: 11, label: "1-1",children: [{value: 111, label: "1-1-1"}]}]}, {value: 2, label: "2"}]保留指定层级的方法 function keepNodesAtLevel(data, level…

vue源码阅读之Watcher类

我们上次分析vue源码讲的是收集依赖&#xff0c;数据变化之后我们把依赖收集到dep类中&#xff0c;通过这个管理器进行管理。 里面有一个subs数组&#xff0c;用来存放依赖&#xff0c;并且定义了几个实例方法用来依赖进行添加&#xff0c;删除&#xff0c;通过操作。 比如ad…

mysql基础5——mysql主从

文章目录 一、基本了解二、主从原理三、主从复制3.1 从无到有3.1.1 服务器初始化3.1.2 配置主库3.1.3 配置从库3.1.4 效果验证 3.2 从有到无3.2.1 主库全备&#xff0c;并同步到从库3.2.2 配置主库3.2.3 配置从库3.2.4 效果验证 四、数据库运维4.1 几个参数4.2 查看进程列表 一…

【案例实战】高并发业务的多级缓存架构一致性解决方案

我们在高并发的项目中基本上都离不开缓存&#xff0c;那么既然引入缓存&#xff0c;那就会有一个缓存与数据库数据一致性的问题。 首先&#xff0c;我们先来看看高并发项目里面Redis常见的三种缓存读写模式。 Cache Aside 读写分离模式&#xff0c;是最常见的Redis缓存模式&a…

树莓派教程2023

摘要&#xff1a;本教程只适用于最新版树莓派64位系统&#xff08;debian11&#xff09; 树莓派官网&#xff08;之前是org&#xff09;&#xff1a; https://www.raspberrypi.com/ 一.烧录系统 1.官网下载官方烧写器 https://downloads.raspberrypi.org/imager/imager_late…