Java编程内功-数据结构与算法「环形链表与约瑟夫问题」

开发 后端 算法
本篇继续给大家带来Java编程内功-数据结构与算法相关内容,今天主要介绍环形链表与约瑟夫问题的相关知识。

[[386837]]

 Josephu问题

设编号为1,2,....n的n个人围坐一圈,约定编号为k(1<<k<<n)的人开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,知道所有人出列为止,由此产生一个出队编号的序列.

循环链表处理Josephu问题

先构成一个有n个节点的单向循环链表,然后由k节点器从1开始计数,计到m时,对应节点从链表删除,然后再从被删除节点的下一个节点又从1开始计数,直到最后一个节点从链表中删除.

构建一个单向环形链表

1. 先创建第一个节点,让first指向该节点,并形成环.

2. 后面每创建一个新的节点,就把该节点,加入环形链表即可.

代码案例

  1. package com.structures.linkedlist; 
  2.  
  3. public class Josephu { 
  4.     public static void main(String[] args) { 
  5.         CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList(); 
  6.         circleSingleLinkedList.addBoy(5); 
  7.         circleSingleLinkedList.showBoys(); 
  8.         circleSingleLinkedList.countBoy(1,2,5); 
  9.  
  10.         /* 
  11.         小孩的编号:1 
  12.         小孩的编号:2 
  13.         小孩的编号:3 
  14.         小孩的编号:4 
  15.         小孩的编号:5 
  16.         小孩2出圈 
  17.         小孩4出圈 
  18.         小孩1出圈 
  19.         小孩5出圈 
  20.         最后留在圈中的小孩编号3 
  21.         */ 
  22.     } 
  23.  
  24. //创建一个环形的单向链表 
  25. class CircleSingleLinkedList { 
  26.     //创建一个first节点,当前没有编号 
  27.     private Boy first = new Boy(-1); 
  28.  
  29.     //添加小孩节点,构建成一个环形链表 
  30.     public void addBoy(int nums) { 
  31.         if (nums < 1) { 
  32.             System.out.println("nums 值不正确"); 
  33.             return
  34.         } 
  35.         Boy curBoy = null
  36.         //for循环创建环形链表 
  37.         for (int i = 1; i <= nums; i++) { 
  38.             Boy boy = new Boy(i); 
  39.             //如果是第一个小孩 
  40.             if (i == 1) { 
  41.                 first = boy; 
  42.                 first.setNext(first); 
  43.                 curBoy = first;//让curBoy指向第一个 
  44.             } else { 
  45.                 curBoy.setNext(boy); 
  46.                 boy.setNext(first); 
  47.                 curBoy = boy; 
  48.             } 
  49.         } 
  50.     } 
  51.  
  52.     //遍历当前环形链表 
  53.     public void showBoys() { 
  54.         if (first.getNext() == null) { 
  55.             System.out.println("没有任何小孩~~"); 
  56.             return
  57.         } 
  58.         Boy temp = first
  59.         while (true) { 
  60.             System.out.println("小孩的编号:" + temp.getNo()); 
  61.             if (temp.getNext() == first) { 
  62.                 break; 
  63.             } 
  64.             temp = temp.getNext(); 
  65.         } 
  66.     } 
  67.  
  68.     /** 
  69.      * 根据用户输入,计算小孩出圈顺序 
  70.      * 
  71.      * @param startNo  表示从第几个小孩开始计数 
  72.      * @param countNum 表示数几下 
  73.      * @param nums     表示多少个小孩在圈中 
  74.      */ 
  75.     public void countBoy(int startNo, int countNum, int nums) { 
  76.         //先进行数据校验 
  77.         if (first == null || startNo < 1 || startNo > nums) { 
  78.             System.out.println("参数输入有误,请重新输入"); 
  79.             return
  80.         } 
  81.         //创建一个辅助指针,帮助完成小孩出圈 
  82.         Boy helper = first
  83.         //让helper指向环形链表的最后节点 
  84.         while (helper.getNext() != first) { 
  85.             helper = helper.getNext(); 
  86.         } 
  87.         //报数前,先让helper和first移动,移动k-1次,这样first定位到开始节点,helper紧接着first 
  88.         for (int i = 0; i < startNo - 1; i++) { 
  89.             first = first.getNext(); 
  90.             helper = helper.getNext(); 
  91.         } 
  92.         //报数时,让first和helper指针同时移动,然后出圈 
  93.         while (true) { 
  94.             //当圈中只有一个节点 
  95.             if (helper == first) { 
  96.                 break; 
  97.             } 
  98.             //让first和helper指针同时移动countNum - 1次 
  99.             for (int i = 0; i < countNum - 1; i++) { 
  100.                 first = first.getNext(); 
  101.                 helper = helper.getNext(); 
  102.             } 
  103.             //此时first节点就是小孩要出圈的节点 
  104.             System.out.printf("小孩%d出圈\n"first.getNo()); 
  105.             first = first.getNext(); 
  106.             helper.setNext(first); 
  107.         } 
  108.         System.out.printf("最后留在圈中的小孩编号%d \n"first.getNo()); 
  109.     } 
  110.  
  111. //创建一个Boy类,表示节点 
  112. class Boy { 
  113.     private int no;//编号 
  114.     private Boy next;//指向下一个节点,默认null 
  115.  
  116.     public Boy(int no) { 
  117.         this.no = no
  118.     } 
  119.  
  120.     public int getNo() { 
  121.         return no
  122.     } 
  123.  
  124.     public void setNo(int no) { 
  125.         this.no = no
  126.     } 
  127.  
  128.     public Boy getNext() { 
  129.         return next
  130.     } 
  131.  
  132.     public void setNext(Boy next) { 
  133.         this.next = next
  134.     } 

 【编辑推荐】

 

责任编辑:姜华 来源: 今日头条
相关推荐

2021-03-10 08:42:19

Java数据结构算法

2021-05-12 09:07:09

Java数据结构算法

2021-03-09 06:30:32

JAVA数据结构算法

2021-04-13 09:37:41

Java数据结构算法

2021-03-18 08:44:20

Java数据结构算法

2021-03-26 08:40:28

Java数据结构算法

2021-03-12 09:13:47

Java数据结构算法

2021-03-23 08:33:22

Java数据结构算法

2021-03-08 06:28:57

JAVA数据结构与算法稀疏数组

2021-03-17 09:27:36

Java数据结构算法

2021-04-15 09:36:44

Java数据结构算法

2021-04-07 09:26:37

Java数据结构算法

2021-04-16 09:40:52

Java数据结构算法

2021-04-22 10:07:45

Java数据结构算法

2021-03-14 08:27:40

Java数据结构算法

2021-04-23 09:12:09

Java数据结构算法

2021-05-13 07:34:56

Java数据结构算法

2021-03-24 10:41:04

Java数据结构算法

2021-05-08 08:28:38

Java数据结构算法

2021-04-27 06:21:29

Java数据结构算法
点赞
收藏

51CTO技术栈公众号