目录

一、约瑟夫问题的内容

二、用代码解决约瑟夫问题(环形链表)

1.什么是环形链表

2.开始解决

解决思路:

全部代码:


一、约瑟夫问题的内容

设编号为1,2,3......n的n个人坐成一圈,编号为k的人开始从1报数,数到m的那个人出列,出列那个人的下一位又从1开始报数,数到m的那个人出列,以此类推,直到所有人都出列为止,由此产生一个出队编号的序列。

举个例子:假如现在有5个小孩坐成一圈,从编号为1的小孩开始报数,数到2的人出列。

 然后编号2出列

数到2的继续出列,以此类推,产生一个出队编号的序列为:24153

那么我们怎么用代码来解决这个问题,直接用代码就可以产生这个编号,下面我们来用C#解决一下这个问题。

二、用代码解决约瑟夫问题(环形链表)

1.什么是环形链表

就是在单链表的基础上,让最后一个节点的next指向第一个节点。如果链表里只有一个节点,那么就让它自己的next指向自己,也构成了环形。

2.开始解决

解决思路:

首先咱们得创建个节点类吧,节点类里包括小孩编号和next指向两个成员变量。(这段代码直接看全部代码,在这里写太啰嗦)

然后就开始创建链表类,链表类里得包含三个方法(第二个方法其实没啥用,就是验证一下第一个方法写对了没),分别为:创建一个环形链表,遍历环形链表,计算出小孩出圈顺序

注意:我们链表类里有一个first指向第一个小孩(节点)。

创建一个环形链表(就是让n个小孩先坐一圈)

思路:

首先需要一个循环语句去添加这么多个节点。

当添加第一个节点时,需要让first和curBoy都指向第一个节点,且需要让第一个节点的next指向自己从而形成一个环形。如下图:

当继续往后添加节点时,只需让最后一个节点的next指向添加的节点(原来的next指向自然就断了),然后现在新添加的节点就是最后一个节点,然后让这个节点的next指向第一个节点,形成环形。还需要把curBoy往后移动一位(不然你下次循环是不是就不对了)。如下图:

 下面看一下代码实现:

    class BoyList{private Boy first = null;//创建一个环形列表public void addBoy(int num){if(num<1){Console.WriteLine("传入的小孩个数不符合要求");return;}Boy curBoy = null;//辅助节点for(int i = 1;i <= num;i++){Boy boy = new Boy(i);if(i == 1){first = boy;first.Next = first;//构成环curBoy = first;}else{curBoy.Next = boy;curBoy = boy;curBoy.Next = first;}}}}

遍历环形链表:

这个和单链表思路差不多。有一个需要注意的地方就是怎么去判断到最后一个节点了,我这里用的思路是,当你的辅助节点curBoy==first时,就说明不需要继续往下遍历了。

解释一下curBoy==first啥意思,其实first和curBoy里存放的都是地址,所以当这两块地址相同时,就说明遍历完了。千万别把这个东西理解为“因为curBoy和first里面的小孩编号都一样,所以遍历完了”,这是错误的理解。

剩下的看代码:

        //遍历环形链表public void showBoy(){//链表为空,没有小孩if(first == null){Console.WriteLine("没有小孩");return;}//链表不为空Boy curBoy = first;//辅助节点while(true){Console.WriteLine("第{0}个小孩",curBoy.No);curBoy = curBoy.Next;if(curBoy == first)//证明已经遍历完了{break;}}}

计算出小孩的出圈顺序(最重要):

这里用了这样一个思路:假如我们先是从第一个小孩开始报数,我们需要一个辅助指针去指向first的前一个节点,如图所示:

怎么让helper去指向first的前一个节点,遍历就行了。

然后开始数数,假如让数m次就出去一个小孩,那咱们就需要把first和helper同时向后移动一下,然后让first指向的那个小孩出去,然后first继续指向下一个小孩。现在假如是数两次出去一个小孩,如下两图:

让第二个小孩出去,其实就是让1的next指向第3个小孩。移出去之前记得先打印一下2,因为移出去之后,就找不到了,垃圾回收器还会自动回收。

就这样去循环,到只剩一个小孩之后停止循环,最后单独打印一下最后一个小孩。

刚才这是假如是从第一个小孩开始报数,那么我们怎么样才能想从哪个小孩开始报数就从哪个小孩开始报数。很简单:我们想从第n个小孩开始报数,那么就让helper和first同时往后移动(n-1)个位置。比如我们想从第二个小孩开始报数,那么只需让helper和first的指向在从第一个小孩开始报数的基础上往后移动一个位置。移动后如图所示:

然后现在该删小孩了,就和上面的删小孩用的同一个代码。

看代码:

        //计算出小孩出圈顺序//startNo 表示从第几个小孩开始数数//countNum 表示数几下//nums 表示最初有几个小孩在圈中public void countBoy(int startNo,int countNum,int nums){//先对数据进行校验if(first == null || countNum < 1 || startNo > nums){Console.WriteLine("输入数据不符合要求");return;}//创建辅助指针Boy helper = first;//假如小孩是从第一个小孩开始报数while (true){if (helper.Next == first){break;}helper = helper.Next;}//小孩是从startNo个小孩开始报数,所以需要移动helper和firstfor(int i = 1;i <= startNo-1;i++){helper = helper.Next;first = first.Next;}//现在开始报数,报数countNum下,helper和first需要移动countNum-1while(true){if(first == helper)//这时只剩下一个小孩{break;}for(int i = 1;i <= countNum-1;i++){helper = helper.Next;first = first.Next;}Console.WriteLine("第{0}个小孩出来了",first.No);helper.Next = first.Next;first = first.Next;}Console.WriteLine("最后一个小孩是{0}",first.No);}

全部代码:

using System;namespace _5.约瑟夫问题
{class Program{static void Main(string[] args){BoyList boyList = new BoyList();boyList.addBoy(5);boyList.showBoy();boyList.countBoy(1, 2, 5);}}class Boy{private int no;//第几个节点(小孩)private Boy next;//指向下一个节点(小孩)public Boy(int no){this.no = no;}public int No{get{return no;}set{no = value;}}public Boy Next{get{return next;}set{next = value;}}}class BoyList{private Boy first = null;//创建一个环形列表public void addBoy(int num){if(num<1){Console.WriteLine("传入的小孩个数不符合要求");return;}Boy curBoy = null;//辅助节点for(int i = 1;i <= num;i++){Boy boy = new Boy(i);if(i == 1){first = boy;first.Next = first;//构成环curBoy = first;}else{curBoy.Next = boy;curBoy = boy;curBoy.Next = first;}}}//遍历环形链表public void showBoy(){//链表为空,没有小孩if(first == null){Console.WriteLine("没有小孩");return;}//链表不为空Boy curBoy = first;//辅助节点while(true){Console.WriteLine("第{0}个小孩",curBoy.No);curBoy = curBoy.Next;if(curBoy == first)//证明已经遍历完了{break;}}}//计算出小孩出圈顺序//startNo 表示从第几个小孩开始数数//countNum 表示数几下//nums 表示最初有几个小孩在圈中public void countBoy(int startNo,int countNum,int nums){//先对数据进行校验if(first == null || countNum < 1 || startNo > nums){Console.WriteLine("输入数据不符合要求");return;}//创建辅助指针Boy helper = first;//假如小孩是从第一个小孩开始报数while (true){if (helper.Next == first){break;}helper = helper.Next;}//小孩是从startNo个小孩开始报数,所以需要移动helper和firstfor(int i = 1;i <= startNo-1;i++){helper = helper.Next;first = first.Next;}//现在开始报数,报数countNum下,helper和first需要移动countNum-1while(true){if(first == helper)//这时只剩下一个小孩{break;}for(int i = 1;i <= countNum-1;i++){helper = helper.Next;first = first.Next;}Console.WriteLine("第{0}个小孩出来了",first.No);helper.Next = first.Next;first = first.Next;}Console.WriteLine("最后一个小孩是{0}",first.No);}}
}

C#数据结构-约瑟夫问题相关推荐

  1. 数据结c语言约瑟夫环实验报告,数据结构约瑟夫环实验报告.doc

    数据结构约瑟夫环实验报告.doc 数据结构与算法设计约瑟夫环实验报告实验一专业物联网工程班级物联网1班学号15180118姓名刘沛航一. 实验目的 1.熟悉VC环境,学习使用C语言利用链表的存储结构解 ...

  2. 数据结构—约瑟夫环问题(C语言版)

    目录 首先什么是约瑟夫环 约瑟夫环实现方式 一.创建结构体变量 二.初始化链表 三.构建循环链表 四.删除链表 五.完整代码及注释讲解 首先什么是约瑟夫环 约瑟夫环是循环链表中的一个经典问题:题目描述 ...

  3. 数据结构约瑟夫环实验报告

    实验目的及要求 目的:能够熟练掌握线性表的基本操作在顺序和链式两种存储结构上的实现,进一步理解线性表的逻辑结构和存储结构,提高使用理论知识指导解决实际问题的能力. 要求:1.建立数据模型,确定存储结构 ...

  4. 数据结构-约瑟夫斯环(cir_sqlink)

    约瑟夫斯环 让n个人围成一个圈,并编号1~n,从编号1的人开始计数,每次杀掉下一个编号的人,直到留下最后幸存者. 比如: n=6,这6个人分别是1,2,3,4,5,6 第一轮,2.4.6位置上的人被杀 ...

  5. Java数据结构-约瑟夫 作者:哇塞大嘴好帥(哇塞大嘴好帅)

    Java 约瑟夫 作者:哇塞大嘴好帥(哇塞大嘴好帅) 作者:哇塞大嘴好帥(哇塞大嘴好帅) 0.Josephu(约瑟夫) 分析 ​ 设编号为1,2,- n的n个人围坐一圈,约定编号为k(1<=k& ...

  6. 数据结构——约瑟夫环(Joseph Circle)

    问题描述: 编号为1,2,...,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数).现在给定一个随机数m>0,从编号为1的人开始,按顺时针方向1开始顺序报数,报到m时停止.报m的人出圈 ...

  7. 算法与数据结构——约瑟夫生者死者游戏

    一.概要设计 编写一个选择第9人进行杀死的函数,由两个循环嵌套,外循环计算总杀死人数,内循环计算第9人,返回人数为存活人数.其中要注意跳过数据域为空的头指针. 总函数中利用循环创建单循环链表,利用数组 ...

  8. C/C++数据结构课程设计安排

    C/C++数据结构课程设计安排 数据结构课程设计安排 课程设计学时:32学时 课程设计目的:综合应用数据结构课程中所学的数据结构:线性表.栈.队列.数组.广义表.树.二叉树.图.查找表中的一种或多种数 ...

  9. Algorithms_基础数据结构(04)_线性表之链表_单向循环链表约瑟夫环问题

    文章目录 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 约瑟夫问题 结构 分析 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 tip:单向链表 约瑟夫问题 N个人围成一圈, ...

最新文章

  1. WPF 中动态创建和删除控件
  2. WAL streaming (max_wal_senders 0) requires wal_level replica or logical
  3. j函数 判断以 什么开头
  4. 介绍50个 WordPress 动作挂钩
  5. BZOJ 1920 Luogu P4217 [CTSC2010]产品销售 (模拟费用流、线段树)
  6. 手握五大成功秘密武器
  7. 【AWSL】之Linux账号和权限管理(/etc/passwd、/etc/shadow、useradd、passwd、usermod、groupadd、gpasswd...chmod、chown)
  8. 凯恩帝k1000ti参数设置_KND1000TI系统参数
  9. mysql语句1=1_mysql - “where 1 = 1”语句
  10. scala类型参数的上界和下界
  11. 地图上制作线路的动画_R制作动画地图
  12. Docker教程:dokcer的配置和命令
  13. latex缩进与对齐_科学网—Latex算法排版,不同行缩进不同 - 张鹏的博文
  14. python实现随机产生数据矩阵,将txt文件写入Excel中以及转置后写入Excel中
  15. 轻松学习Linux之入门篇
  16. 雷达水位计的工作原理及安装维护注意事项
  17. 赖美云的认证照_火箭少女最新路透照出炉:吴宣仪赖美云魅力十足,张紫宁傅菁凭颜值圈粉...
  18. Python爬虫,爬取51job上有关大数据的招聘信息
  19. Spring配置文件报错 :通配符的匹配很全面, 但无法找到元素 ‘context:property-placeholder‘ 的声明
  20. JavaScript设计模式有哪些?

热门文章

  1. P265GH钢板牌号和化学元素
  2. 【PHP】把时间戳改为多长时间之前
  3. Linux pwn入门教程,pwn堆入门系列教程1
  4. 为什么电脑连接不上FTP
  5. 无限法则台湾服务器什么时间开测,《无限法则》什么时候可以玩 公测上线时间介绍...
  6. 读书百客:《五美吟·红拂》赏析
  7. 十六进制随机颜色的引用说明
  8. 层次聚类算法(hierarchial cluster)
  9. Win8如何升级Win8.1
  10. 微信小程序项目开发实战:用WePY、mpvue、Taro打造高效的小程序》(笔记4)支持React.js语法的Taro框架