约瑟夫环(Java) 素颜马尾好姑娘i 2024-04-08 10:59 62阅读 0赞 单向环形链表 ![e5aed0f70dec4349b58aeea6c6ead1f3.png][] 这个应用场景的思路来自韩顺平的数据结构和算法教程。哔哩哔哩有教程。在第27-29p就是约瑟夫环。三段视频好像就1个小时的时间。二倍速的话不到半小时。你可以先快速看完韩老师的教程再来copy我的代码。这样就能真正的掌握知识点啦! 不过我的代码是用idea写的。韩老师的是eclipse写的。我的代码可能和老师的代码有所区别。所以,我会放上我的代码和韩老师的代码。大家自行选择吧!废话不多说,直接上代码。 还是那句话,授人以鱼不如授人以渔。学到了,才是你的知识点。 这是我的代码运行的界面图 ![f733758ac652445ba85f704e3cb610ba.png][] 这是我的代码 package com.ldm.linkedlist; /** * @author 梁东明 * 2022/8/22 * 86139 * 点击setting在Editor 的File and Code Templates 修改 */ public class JosepFu { public static void main(String[] args) { CircleLinkedList circleLinkedList = new CircleLinkedList(); circleLinkedList.addNode(34); circleLinkedList.show(); //测试出链表是否正确 circleLinkedList.countNode(3,2,34); } } //环形链表 class CircleLinkedList{ //定义头节点,先占着位置,不拉屎。 private Node first = null; //添加节点的方法 public void addNode(int nums){ //判断链表是否为null if (nums < 1) { System.out.println("这是一个空链表"); return; } //辅助变量 Node cur = null; //先让cur指向first //for循环创建链表 for (int i = 1; i <= nums; i++) { //根据编号创建节点 Node node = new Node(i); if (i == 1) { first = node; //私有属性不能通过 first.next = first来赋值 first.setNext(first); //自己指向自己,循环链表开始雏形 cur = first; }else { cur.setNext(node); node.setNext(first); cur = node; //本来cur = cur.next 来遍历的 //但是38行的代码已经让cur.next = node //所以 cur = node 就行了 } } } //遍历环形单链表 public void show(){ //判断链表是否为null if (first == null) { System.out.println("没有任何节点"); return; } //辅助变量 Node cur = first; while (true) { System.out.println("节点的编号是:"+cur.getNo()); if (cur.getNext() == first) { break; } cur = cur.getNext(); } } //根据用户输入,判断节点抛出链表的顺序 /** * * @param k 表示从第几个节点开始数数 * @param m 表示数多少下,数到谁,谁就抛出链表 * @param nums 表示一开始链表有多少个节点 */ public void countNode(int k,int m,int nums){ //对链表检验 //这里怕麻烦,就不让nums > k ,否则要取模很麻烦 if (first == null || k < 1 || k > nums ) { System.out.println("参数有误,请重新输入"); return; } //创建辅助变量 Node helper = first; //helper应该事先指向环形链表的最后一个节点 while (true) { if (helper.getNext() == first) {//说明helper已经指向最后一个节点 break; } helper = helper.getNext(); } //在m开始数数之前,先让helper和first移动 k - 1 次 for (int i = 0; i < k-1; i++) { first = first.getNext(); helper = helper.getNext(); } //m开始数数的时候,让helper和first移动 m - 1 次 //这样就把数到的那个节点移出链表 这是一个循环操作,直到链表只剩下最后一个节点 int count = 0; while (true) { if (helper == first) { //说明链表只剩下一个节点,跳出循环,该节点获胜 break; } //m开始数数的时候,让helper和first移动 m - 1 次 for (int j = 0; j < m - 1; j++) { first = first.getNext(); helper = helper.getNext(); count ++; } //当退出for循环表示第k个节点开始从1开始报数,数到m这个节点,就被淘汰 //这时,first指向的节点,就是要被淘汰的节点 //这段是可以输出第几个被淘汰的节点,遗憾的是我不会处理 m为1的情况。所以尽量别用 System.out.println("第"+(count / (m-1))+"个被淘汰的节点是:" + first.getNo()); //用这个就没有/ by zero 的异常了。 //System.out.println("被淘汰的节点是:" + first.getNo()); //这时候,把first指向被淘汰的节点 first = first.getNext(); helper.setNext(first); } System.out.println("胜利节点为" +helper.getNo()); } } //节点类 class Node{ //看清楚,我这里两个属性都是私有的,等下被调用时只能通过set、get方法获取或者赋值 private int no; //看清楚,我这里两个属性都是私有的,等下被调用时只能通过set、get方法获取或者赋值 private Node next; public Node(int no) { this.no = no; } public int getNo() { return no; } public void setNo(int no) { this.no = no; } public Node getNext() { return next; } public void setNext(Node next) { this.next = next; } } 这是韩老师的代码运行界面 ![c97d42390a8946e5a2dbe20ae0ac1eef.png][] 这是韩老师的代码 package com.ldm.LinkedList; public class Josepfu { public static void main(String[] args) { // 测试一把看看构建环形链表,和遍历是否ok CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList(); circleSingleLinkedList.addBoy(5);// 加入5个小孩节点 circleSingleLinkedList.showBoy(); //测试一把小孩出圈是否正确 circleSingleLinkedList.countBoy(1, 2, 5); // 2->4->1->5->3 //String str = "7*2*2-5+1-5+3-3"; } } // 创建一个环形的单向链表 class CircleSingleLinkedList { // 创建一个first节点,当前没有编号 private Boy first = null; // 添加小孩节点,构建成一个环形的链表 public void addBoy(int nums) { // nums 做一个数据校验 if (nums < 1) { System.out.println("nums的值不正确"); return; } Boy curBoy = null; // 辅助指针,帮助构建环形链表 // 使用for来创建我们的环形链表 for (int i = 1; i <= nums; i++) { // 根据编号,创建小孩节点 Boy boy = new Boy(i); // 如果是第一个小孩 if (i == 1) { first = boy; first.setNext(first); // 构成环 curBoy = first; // 让curBoy指向第一个小孩 } else { curBoy.setNext(boy);// boy.setNext(first);// curBoy = boy; } } } // 遍历当前的环形链表 public void showBoy() { // 判断链表是否为空 if (first == null) { System.out.println("没有任何小孩~~"); return; } // 因为first不能动,因此我们仍然使用一个辅助指针完成遍历 Boy curBoy = first; while (true) { System.out.printf("小孩的编号 %d \n", curBoy.getNo()); if (curBoy.getNext() == first) {// 说明已经遍历完毕 break; } curBoy = curBoy.getNext(); // curBoy后移 } } // 根据用户的输入,计算出小孩出圈的顺序 /** * * @param startNo * 表示从第几个小孩开始数数 * @param countNum * 表示数几下 * @param nums * 表示最初有多少小孩在圈中 */ public void countBoy(int startNo, int countNum, int nums) { // 先对数据进行校验 if (first == null || startNo < 1 || startNo > nums) { System.out.println("参数输入有误, 请重新输入"); return; } // 创建要给辅助指针,帮助完成小孩出圈 Boy helper = first; // 需求创建一个辅助指针(变量) helper , 事先应该指向环形链表的最后这个节点 while (true) { if (helper.getNext() == first) { // 说明helper指向最后小孩节点 break; } helper = helper.getNext(); } //小孩报数前,先让 first 和 helper 移动 k - 1次 for(int j = 0; j < startNo - 1; j++) { first = first.getNext(); helper = helper.getNext(); } //当小孩报数时,让first 和 helper 指针同时 的移动 m - 1 次, 然后出圈 //这里是一个循环操作,知道圈中只有一个节点 while(true) { if(helper == first) { //说明圈中只有一个节点 break; } //让 first 和 helper 指针同时 的移动 countNum - 1 for(int j = 0; j < countNum - 1; j++) { first = first.getNext(); helper = helper.getNext(); } //这时first指向的节点,就是要出圈的小孩节点 System.out.printf("小孩%d出圈\n", first.getNo()); //这时将first指向的小孩节点出圈 first = first.getNext(); helper.setNext(first); // } System.out.printf("最后留在圈中的小孩编号%d \n", first.getNo()); } } // 创建一个Boy类,表示一个节点 class Boy { private int no;// 编号 private Boy next; // 指向下一个节点,默认null public Boy(int no) { this.no = no; } public int getNo() { return no; } public void setNo(int no) { this.no = no; } public Boy getNext() { return next; } public void setNext(Boy next) { this.next = next; } } 最后的最后,介绍一下,我是小白,希望能成为一名合格的程序员。 [e5aed0f70dec4349b58aeea6c6ead1f3.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/08/dd7f5cbf89b6425bbffa3dac54e6592a.png [f733758ac652445ba85f704e3cb610ba.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/08/4d210c169d1045e6881b32b1e735b650.png [c97d42390a8946e5a2dbe20ae0ac1eef.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/08/ea52a1316efa4c2da21a19d82658d18b.png
相关 约瑟夫环(Java) 单向环形链表 ![e5aed0f70dec4349b58aeea6c6ead1f3.png][] 这个应用场景的思路来自韩顺平的数据结构和算法教程。哔哩哔哩有教程。在第27 素颜马尾好姑娘i/ 2024年04月08日 10:59/ 0 赞/ 63 阅读
相关 约瑟夫环 约瑟夫环 1、参考资料 https://blog.csdn.net/shuaicihai/article/details/54847433 2、使用数组 痛定思痛。/ 2022年11月27日 06:54/ 0 赞/ 185 阅读
相关 约瑟夫环 package com.someusefuldesign.demo; import java.util.ArrayList; /约瑟 桃扇骨/ 2022年08月13日 15:54/ 0 赞/ 183 阅读
相关 约瑟夫环 \include<stdio.h> \include<stdlib.h> /\ 约瑟夫环是一个数学的应用问题: 已知n个人(以编号1,2,3...n分别表示)围 ╰半夏微凉°/ 2022年08月07日 01:53/ 0 赞/ 204 阅读
相关 约瑟夫环 约瑟夫环 约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个 怼烎@/ 2022年07月15日 13:39/ 0 赞/ 199 阅读
相关 约瑟夫环 N个人坐成一个圆环(编号为1 - N),从第1个人开始报数,数到K的人出列,后面的人重新从1开始报数。问最后剩下的人的编号。 例如:N = 3,K = 2。2号先出列,然后是 桃扇骨/ 2022年06月11日 06:26/ 0 赞/ 208 阅读
相关 约瑟夫环 【问题描述】 编号为 1,2,...,n 的 n 个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。现在给定一个随 机数 m>0,从编号为 1 的人开始,按顺时针方向 1 今天药忘吃喽~/ 2022年04月22日 06:06/ 0 赞/ 254 阅读
相关 约瑟夫环 > 约瑟夫环运作如下: > 1、一群人围在一起坐成 \[2\] 环状(如:N) > 2、从某个编号开始报数(如:K) > 3、数到某个数(如:M)的时候,此人出列, 阳光穿透心脏的1/2处/ 2022年03月22日 16:38/ 0 赞/ 303 阅读
相关 约瑟夫环 约瑟夫环:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规 曾经终败给现在/ 2022年02月28日 00:54/ 0 赞/ 238 阅读
相关 约瑟夫环 编号为1,2,…,n的n个人按顺时针方向围坐在一张圆桌周围,每人持有一个密码(正整数)。一 开始任选一个正整数m作为报数上限值,从第一个人开始按顺时针方向自1开始报数,报到m时 r囧r小猫/ 2021年12月20日 04:29/ 0 赞/ 321 阅读
还没有评论,来说两句吧...