数据结构之单向环形列表解决josef问题
1.定义节点类
该节点类中只有孩子的编号,以及指向下一个节点的"指针"
package com.ebiz.list.josepfu; /** * @author YHj * @create 2019-07-17 22:21 * 表示节点的类 */ public class Boy { private int no; private Boy next; //指向下一个节点 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; } @Override public String toString() { return "我是第" + no + "个Boy"; } }
2.定义单向链表类
需要注意的是,josef问题是头尾相连的,在这也就是最后一个节点需要指向第一个节点,如果只有一个节点,那么该节点需要指向节点本身.
解决josef问题,关键是理解最后的josef方法.
package com.ebiz.list.josepfu; /** * @author YHj * @create 2019-07-17 22:16 * 环形单项链表 */ public class SingleCircleList { //创建一个first 节点 没有编号也可以为空 private Boy firstBoy =new Boy(-1); //添加节点,构成环形链表 需要注意的是第一个节点需要指向节点本身 public void add(int num){ if (num < 1 ){ System.out.println("编号不正确"); return; } //创建辅助节点 Boy temp=null; //添加节点 for (int i = 1; i <=num ; i++) { Boy boy = new Boy(i); if (i == 1){ //代表第一个节点 firstBoy=boy; firstBoy.setNext(firstBoy); temp=firstBoy; //辅助接点 }else { temp.setNext(boy); boy.setNext(firstBoy); //这里不能为temp 因为是环形链表,后面逐渐增加的节点的next应该是头节点 temp=boy; } } } //遍历环形链表 public void list( ){ if (firstBoy.getNo() == -1){ System.out.println("该环形链表为空!"); return; } //定义辅助指针 Boy temp=firstBoy; while (true){ System.out.println(temp); if (temp.getNext().getNo() == 1){ break; } temp=temp.getNext(); } } /* josepfu问题的实现 根据用户的输入,生成小孩出圈的顺序 k:从哪里开始 m:数几下 num:玩游戏的小孩的数量 */ public void josepfu(int k,int m,int num){ //数据校验 if (k>num || k<1 || m<1 || num<1){ System.out.println("参数输入有误"); } if(firstBoy.getNo() == -1){ System.out.println("链表节点为空!"); } //创建辅助指针 帮助小孩完成出圈 Boy temp=firstBoy; //循环遍历,将该辅助指针指向最后一个,即firstBoy前一个 while (true){ if(temp.getNext() == firstBoy){ break; } temp=temp.getNext(); } // 报数之前.让first 和temp移动到对应位置 在k处报数,让first和temp移动k-1, // 移动到开始报数的孩子身上 for (int i = 1; i <=k-1 ; i++) { firstBoy=firstBoy.getNext(); temp=temp.getNext(); } while (true){ if (firstBoy == temp){ break; } //开始报数,第k个孩子,即firstBoy当前指向的孩子 //报m个数,,从第k个孩子本身报数,所以firstBoy移动m-1次,temp也移动m-1次 for (int i = 1; i <=m-1 ; i++) { firstBoy=firstBoy.getNext(); temp=temp.getNext(); } //上面循环结束时,firstBoy指向要出去的孩子 System.out.printf("小孩%d出圈",firstBoy.getNo()); //这是将firstBoy指向将要出去的孩子的下一位,并且temp的next指向他 firstBoy=firstBoy.getNext(); temp.setNext(firstBoy); } System.out.printf("最后留在圈中的小孩编号%d",firstBoy.getNo()); //或者temp } }
3. 写一个简单测试类
package com.ebiz.list.josepfu; /** * @author YHj * @create 2019-07-18 9:30 */ public class Test { public static void main(String[] args) { //创建环形链表 SingleCircleList circleList = new SingleCircleList(); //环形链表添加节点 circleList.add(5); //遍历链表 circleList.list(); circleList.josepfu(1,2,5); } }
有不懂的欢迎留言评论!