李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
Java
正文
数据结构学习--单向环形链表
Leefs
2020-01-28 PM
3219℃
0条
# 数据结构学习--单向环形链表 ### 一、单向环形链表的应用场景 **Josephu**(约瑟夫、约瑟夫环) **问题** Josephu 问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。 **提示**:用一个不带头结点的循环链表来处理Josephu 问题:先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除算法结束。 ![06.单向环形链表01.png][1] ### 二、单向环形链表介绍 ![06.单向环形链表02.png][2] ### 三、Josephu问题 **约瑟夫问题的示意图** ![06.单向环形链表03.png][3] **创建环形链表的思路图解** ![06.单向环形链表04.png][4] **构建一个单向的环形链表的思路** > 1. 1.先创建第一个节点,让first指向该节点,并形成环形 > > 2. 2.后面当我们每创建一个新的节点,就把该节点,加入到已有的环形链表中即可。 **遍历环形链表** > 1. 1.先让一个辅助指针(变量)`curBoy`,指向first节点 > 2. 2.然后通过一个while循环遍历该环形链表即可`curBoy.next==first`结束 **小孩出圈的思路分析图** ![06.单向环形链表05.png][5] ``` 根据用户的输入,生成一个小孩出圈的顺序 n = 5 , 即有5个人 k = 1, 从第一个人开始报数 m = 2, 数2下 ``` **思路** > 1. 1.需求:创建一个辅助指针(变量)helper,事先应该指向环形链表的最后这个节点。 > 2. 2.小孩报数前,先让first和helper移动k-1次 > 3. 3.当小孩报数时,让first和helper指针同时的移动m-1次 > 4. 4.这时可以将first指向的小孩节点出圈 > + first=first.next > + helper.next=first > + 原来first指向的节点就没有任何引用,就会被回收 > > 出圈的顺序 > > 2-->4-->1-->5-->3 **代码实现** ```java package dataStructure; public class Josephu { public static void main(String[] args) { //测试 CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList(); circleSingleLinkedList.addBoy(5); circleSingleLinkedList.showBoy(); //测试小孩出圈是否正确 circleSingleLinkedList.countBoy(1,2,5); } } //创建一个环形的单向链表 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
运行结果 ``` 小孩的编号1 小孩的编号2 小孩的编号3 小孩的编号4 小孩的编号5 小孩2出圈 小孩4出圈 小孩1出圈 小孩5出圈 最后留在圈中的小孩编号3 ``` [1]: https://lilinchao.com/usr/uploads/2020/01/3413407591.png [2]: https://lilinchao.com/usr/uploads/2020/01/1688036218.png [3]: https://lilinchao.com/usr/uploads/2020/01/941271021.png [4]: https://lilinchao.com/usr/uploads/2020/01/3128624935.png [5]: https://lilinchao.com/usr/uploads/2020/01/2523168718.png
标签:
数据结构
,
链表
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:
https://lilinchao.com/archives/491.html
上一篇
数据结构学习--双向链表
下一篇
数据结构学习--栈(一)
取消回复
评论啦~
提交评论
栏目分类
随笔
2
Java
326
大数据
229
工具
35
其它
25
GO
48
NLP
8
标签云
Linux
栈
Ray
VUE
Spark
BurpSuite
容器深入研究
Spark RDD
队列
链表
Azkaban
Hive
Java
Yarn
pytorch
Spark Core
Sentinel
机器学习
JavaWEB项目搭建
数学
Spring
GET和POST
高并发
Java编程思想
Livy
查找
Redis
Beego
RSA加解密
Docker
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞