数据结构运用-单向环形链表应用场景
数据结构运用-单向环形链表应用场景
Josephu(约瑟夫、约瑟夫环) 问题
Josephu 问题为:设编号为 1,2,… n 的 n 个人围坐一圈,约定编号为 k(1<=k<=n)的人从 1 开始报数,数 到 m 的那个人出列,它的下一位又从 1 开始报数,数到 m 的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。
提示:用一个不带头结点的循环链表来处理 Josephu 问题:先构成一个有 n 个结点的单循环链表,然后由 k 结 点起从 1 开始计数,计到 m 时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从 1 开始计数,直到最后一个结点从链表中删除算法结束。
源码
package com.orz.LinkList; /** * @author orz * @create 2020-10-25 13:06 */ public class Josephu { public static void main(String[] args) { CircleSingleLinkedList list=new CircleSingleLinkedList(); list.add(6); System.out.println("环形链表"); list.show(); System.out.println("开始数数"); list.getJosephuPoint(2,3); } } class CircleSingleLinkedList{ //定义一个首节点 private JosephuNode first=new JosephuNode(-1); //根据数值生成环形链表 public void add(int nums) { if(nums<1) { System.out.println("数据不正确"); return; } //辅助节点 JosephuNode cur=null; for (int i=1;i<=nums;i++) { JosephuNode temp=new JosephuNode(i); if(i==1) { first=temp; //形成环 first.setNext(temp); cur=first; } else { cur.setNext(temp); //回指first节点,构成环 temp.setNext(first); cur=cur.getNext(); } } } //展示环形链表 public void show() { if(first.getNext()==null) { System.out.println("链表为空"); return; } //辅助节点 JosephuNode temp=first; while (true) { System.out.println(temp); //循环结束 if(temp.getNext() == first) { break; } temp = temp.getNext(); } } //约瑟夫问题求解 public void getJosephuPoint(int firstCount,int countNumber) { if(first.getNext()==null) { System.out.println("队列为空"); return; } //定义helper、firstCountNode作为循环辅助节点 JosephuNode helper=null; JosephuNode firstCountNode=null; //temp用于找到从哪个节点开始数数 JosephuNode temp=first; //标记节点是否存在 boolean flag=false; //找出第一个数数的节点 while (true) { if(temp.getNext().getNo()==firstCount) { flag=true; break; } if(temp.getNext()==first) { break; } temp=temp.getNext(); } //如果节点不存在,直接退出 if (!flag) { System.out.println("该编号不存在"); return; } //helper指向第一个数数的节点的前一个 //firstCountNode指向第一个数数的节点 helper=temp; firstCountNode=helper.getNext(); while (true) { //节点开始数数 for(int i=0;i<countNumber-1;i++) { firstCountNode=firstCountNode.getNext(); helper=helper.getNext(); } //本轮选择的节点 System.out.println(firstCountNode); //当helper==firstCountNode表明最后只有一个节点,退出循环 if(helper==firstCountNode) { break; } //选择的节点出圈,节点下移 firstCountNode=firstCountNode.getNext(); //helper连接下一个节点 helper.setNext(firstCountNode); } } public JosephuNode getFirst() { return first; } public void setFirst(JosephuNode first) { this.first = first; } } class JosephuNode{ private int no; private JosephuNode next; public JosephuNode(int no) { this.no = no; } public int getNo() { return no; } public void setNo(int no) { this.no = no; } public JosephuNode getNext() { return next; } public void setNext(JosephuNode next) { this.next = next; } @Override public String toString() { return "JosephuNode{" + "no=" + no + '}'; } }