C#线性表约瑟夫环(Joseph Ring)
约瑟夫环
已知N个人围成一个圆圈,每隔M个元素,就清除该元素,剩下的继续:每隔M个元素,就清除该元素,直到元素只有(M-1)个为止。
n个人排成一圈。从某个人开始,按顺时针方向依次编号。
从编号为1的人开始顺时针“一二一”报数,报到2的人退出圈子。这样不断循环下去,圈子里的人将不断减少。由于人的个数是有限的,因此最终会剩下一个人。
试问最后剩下的人最开始的编号。
约瑟夫环是一个循环列表问题。我们用三种线性数据结构来分别实现,同时打印算法用时。
第一种:移除指定位置的元素,每隔N个元素就清除,使用List<T>的RemoveAt(index)
第二种:使用T[] array,bool[] flagArray,第一个数组代表集合数据,第二个数组代表是否已删除标记
第三种:我们使用元组列表来实现Tuple<T,bool> 第一项代表集合数据,第二项代表是否已删除标记
新建.net 5.0控制台应用程序JosephRingDemo,输入测试程序如下:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Linq;namespace JosephRingDemo
{class Program{static void Main(string[] args){int divide = 3;//列表List<string> stringlist = new List<string>() { "大魔法师", "山丘之王", "圣骑士", "血魔法师","剑圣", "先知", "牛头人酋长", "暗影猎手","死亡骑士", "巫妖", "地穴领主", "恐惧魔王","恶魔猎手", "丛林守护者", "守望者", "月之女祭司","驯兽师", "黑暗游侠", "深渊魔王", "娜迦女海巫","火焰领主", "炼金术士", "地精修补匠", "熊猫酒仙","AA","BB","CC","DD","EE","FF","GG","HH","II","JJ","KK","LL","MM","NN","OO","PP","QQ","RR","SS","TT","UU","VV","WW","XX","YY","ZZ"};//数组string[] array = stringlist.ToArray();bool[] flagArray = new bool[array.Length];//元组的第一项代表姓名[string],第二项代表是否已删除标志[bool](默认都未删除)List<Tuple<string, bool>> tupleList = new List<Tuple<string, bool>>();for (int i = 0; i < stringlist.Count; i++){tupleList.Add(Tuple.Create(stringlist[i], false));}JosephRing(stringlist, divide);Console.WriteLine($"【使用List<string>集合】当前集合剩余元素【{string.Join(",", stringlist)}】");JosephRing(array, flagArray, divide);List<string> tempList = new List<string>();for (int i = 0; i < array.Length; i++){if (!flagArray[i]) {tempList.Add(array[i]);}}Console.WriteLine($"【使用string[]和bool[]集合】当前集合剩余元素【{string.Join(",", tempList)}】");JosephRing(tupleList, divide);Console.WriteLine($"【使用List<Tuple<string, bool>>集合】当前集合剩余元素【{string.Join(",", tupleList.FindAll(tuple => !tuple.Item2).Select(tuple => tuple.Item1))}】");Console.ReadLine();}/// <summary>/// 约瑟夫环一:【使用列表集合】每隔divide个元素就从集合中删除/// </summary>/// <param name="list">集合</param>/// <param name="divide">分割计数,每隔几个移除</param>static void JosephRing(List<string> list, int divide){if (list == null) {throw new ArgumentNullException("集合list不能为空");}if (divide <= 0) {throw new ArgumentOutOfRangeException("分割计数必须为正整数");}Contract.EndContractBlock();Stopwatch stopwatch = Stopwatch.StartNew();int cnt = 0;//记录移除的元素集合List<string> removeList = new List<string>();//如果集合的个数 大于 (分割数-1)while (list.Count > divide - 1){for (int index = 0; index < list.Count; index++){cnt++;if (cnt >= divide){//Console.WriteLine($"【{list[index]}】被移除...");removeList.Add(list[index]);list.RemoveAt(index);index--;cnt = 0;}}}Console.WriteLine($"---约瑟夫环一:依次移除的元素集合【{string.Join(",", removeList)}】");Console.WriteLine($"---约瑟夫环一:【使用列表集合】,算法用时【{stopwatch.Elapsed.TotalMilliseconds}】ms");}/// <summary>/// 约瑟夫环二:【使用数组】隔divide个元素就将元素状态设置为已删除/// </summary>/// <param name="array">姓名数组,必须与是否删除标记数组flagArray长度一致</param>/// <param name="flagArray">标记数组,必须与姓名数组array长度一致</param>/// <param name="divide"></param>static void JosephRing(string[] array, bool[] flagArray, int divide) {if (array == null){throw new ArgumentNullException("数组array不能为空");}if (flagArray == null){throw new ArgumentNullException("数组flagArray不能为空");}if (array.Length != flagArray.Length) {throw new ArgumentOutOfRangeException($"对应数组的元素个数不一致:【{array.Length}】vs【{flagArray.Length}】");}if (divide <= 0){throw new ArgumentOutOfRangeException("分割计数必须为正整数");}Contract.EndContractBlock();Stopwatch stopwatch = Stopwatch.StartNew();int cnt = 0;//记录移除的元素集合List<string> removeList = new List<string>();//如果存在未删除状态的集合个数 大于 (分割数-1)while (flagArray.ToList().FindAll(element => !element).Count > divide - 1){for (int index = 0; index < array.Length; index++){//如果某个元素没有被删除if (!flagArray[index]){cnt++;}if (cnt >= divide){//Console.WriteLine($"【{array[index]}】被标记为已删除状态...");removeList.Add(array[index]);flagArray[index] = true;cnt = 0;}}}Console.WriteLine($"---约瑟夫环二:依次移除的元素集合【{string.Join(",", removeList)}】");Console.WriteLine($"---约瑟夫环二:【使用数组】,算法用时【{stopwatch.Elapsed.TotalMilliseconds}】ms");}/// <summary>/// 约瑟夫环三:【使用元组集合】每隔divide个元素就将元素状态设置为已删除/// </summary>/// <param name="tupleList"></param>/// <param name="divide"></param>static void JosephRing(List<Tuple<string, bool>> tupleList, int divide){if (tupleList == null){throw new ArgumentNullException("集合tupleList不能为空");}if (divide <= 0){throw new ArgumentOutOfRangeException("分割计数必须为正整数");}Contract.EndContractBlock();Stopwatch stopwatch = Stopwatch.StartNew();int cnt = 0;//记录移除的元素集合List<string> removeList = new List<string>();//如果存在未删除状态的集合个数 大于 (分割数-1)while (tupleList.FindAll(tuple => !tuple.Item2).Count > divide - 1){for (int index = 0; index < tupleList.Count; index++){//如果某个元素没有被删除if (!tupleList[index].Item2){cnt++;}if (cnt >= divide){//Console.WriteLine($"【{tupleList[index].Item1}】被标记为已删除状态...");removeList.Add(tupleList[index].Item1);//注意 不能使用 tupleList[index].Item2 = true; 元组的第几项是只读的tupleList[index] = new Tuple<string, bool>(tupleList[index].Item1, true);cnt = 0;}}}Console.WriteLine($"---约瑟夫环三:依次移除的元素集合【{string.Join(",", removeList)}】");Console.WriteLine($"---约瑟夫环三:【使用元组集合】,算法用时【{stopwatch.Elapsed.TotalMilliseconds}】ms");}}
}
运行结果如图:
算法性能:元组----->数组----->列表
C#线性表约瑟夫环(Joseph Ring)相关推荐
- I00032 约瑟夫环(Joseph problem)
有关约瑟夫环的介绍,可以参见百度百科的约瑟夫环. 程序中假定人数n小于100,输入数据为n和m.其中,n为人数,数到第m个人出局.输出出局人的顺序.输入数据为0和0时程序结束. AC的C语言程序如下: ...
- 数据结构——约瑟夫环(Joseph Circle)
问题描述: 编号为1,2,...,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数).现在给定一个随机数m>0,从编号为1的人开始,按顺时针方向1开始顺序报数,报到m时停止.报m的人出圈 ...
- Algorithms_基础数据结构(04)_线性表之链表_单向循环链表约瑟夫环问题
文章目录 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 约瑟夫问题 结构 分析 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 tip:单向链表 约瑟夫问题 N个人围成一圈, ...
- 线性表进阶___约瑟夫环问题
/*** 解决约瑟夫环问题:古代某法官要判决n个犯人,荒唐的法律:将犯人站成一个圈,从第S个人开始数起* 每数到第D个犯人,就拉出来处决,再从下一个开始数D个,数到的人再处决,直到剩下最后一个犯人予以 ...
- PTA 线性表 7-1 约瑟夫环(Josephus)问题(by Yan) (100分) 按出列次序输出每个人的编号
7-1 约瑟夫环(Josephus)问题(by Yan) (100分) 编号为1,2,-,n的n个人按顺时针方向围坐在一张圆桌周围,每人持有一个密码(正整数).一开始任选一个正整数m作为报数上限值,从 ...
- 约瑟夫环问题2(顺序表+链表求解)
1.背景知识 * 古代判官要判决number个罪犯的死刑,制定了一条荒谬的法律 * 将犯人站成一个圈,从start开始数起,每数到第distance * 个就处决他,依照此规律直到最后剩下一个人赦免. ...
- 单链表-两个线性表的合并1(破环原链表+尾插法)
题意: 令L1 = (X1,X2,X3,X4-Xn), L2 = (y1,y2,y3,y4-ym);是两个线性表.采用带头节点的链表存储,设计一个算法合并L1,L2,结果放在线性表L3中,要求如下: ...
- UVA1363 LA3521 POJ2800 ZOJ2646 Joseph‘s Problem【约瑟夫环+数学】
Joseph's Problem Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7906 Accepted: 2107 Desc ...
- 深度剖析Josephus ring(约瑟夫环)C语言版
深度剖析Josephus ring(约瑟夫环)C语言版 鉴于C语言更适合展示算法的底层设计,并且便于读者的研究与思考,故而小编使用C语言来展示约瑟夫环的精巧与奥妙. Hello!!各位同学们,欢迎来到 ...
- hdu1443 Joseph(约瑟夫环)
问题:有2k个人,前k个是好人,后k个是坏人,要求最小的m,使得k个坏人在好人之前. 思路: 约瑟夫环递归式为F(n,k)=(F(n-1,k) + k) mod n.其中F(n,k)表示n个人,每一次 ...
最新文章
- 三代测序的基本原理、组装方法和应用场景
- php.ini文件找不到
- java.nio.Buffer flip()方法
- 如何删除webstrom中生成的.idea wrokspace
- Python可以这样学(第二季:tkinter案例精选)-董付国-专题视频课程
- SQLi LABS Less-19
- 大企业都在用的开源 ForgeRock OpenAM 被曝预认证 RCE 0day
- golang 判断map的键key是否存在
- PCB加工文件—Gerber文件的导出(转载)
- 视频播放设计测试用例
- Menhera酱全套表情包
- 日语的汉(训读)字音读音便规则
- 测试发文章测试发文章
- 卷积神经网络残差计算
- Centos7.2安装搜狗拼音
- js接收java数组对象_js接收并转化Java中的数组对象的方法
- Webpack 常用知识点总结
- 无线传感器网络定位算法
- surface pro4-7安装黑苹果教程
- seaJS 简要介绍和完整例子
热门文章
- 社交网络叠加直播功能,会产生什么化学反应?
- 2019杭电多校 Snowy Smile hdu6638 (线段树最大子段和)
- 使用selenium爬取百合网
- 保存到千牛服务器的文件在哪里,压缩包里的文件保存后在哪里?
- mysql每五分钟取一次数据_mysql – 给定时间内每5分钟的平均数据
- 迅雷7计算机丢失xlfsio.dll,求大神帮忙,迅雷7出现的崩溃问题
- 记梦之三:我成了萧峰
- 纽约大学文科学院计算机,2016年美国大学文科排名大全
- 7-14 然后是几点 (15 分)有时候人们用四位数字表示一个时间,比如 1106 表示 11 点零 6 分。现在,你的程序要根据起始时间和流逝的时间计算出终止时间。
- 计算机研究院分所烟台,综合新闻_中科院计算所烟台分所 烟台中科网络技术研究所...