环形链表

一.简介:

环形链表也叫循环链表(可以是双链表、也可以是单链表),操作原理和单链表差不多,只是最后一个节点不在指向空(null)而是头(head),这里以单链表举例:

 

 

 

二.代码实现约瑟夫问题

 

 

 

1)构建一个单向的环形链表思路

  • 先创建第一个节点,让first指向该节点,并形成环形
  • 后面当我们每创建一个新的节点,就把该节点加入到已有的环形链表中即可。

2)遍历环形链表

  • 先让一个辅助指针(变量)curBoy,指向first节点
  • 然后通过一个while循环遍历该环形链表即可,curBoy.next == first结束

 

5. 约瑟夫问题小孩出圈的思路分析

 

 

1
1.定义孩子类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Boy {
    private  int no;//编号
    private  Boy next;//指向下一个节点
 
    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;
    }
 
    public Boy(int no) {
        this.no = no;
    }
}

  

1
2.定义循环链表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
public class CircleSingleLinkedList {
    private Boy first = new Boy(-1);
    //添加小孩节点,构建一个环形链表
    public  void addBoy(int nums){
        //参数校验
        if (nums<1){
            System.out.println("nums的值不正确");
            return;
        }
        Boy curBoy = null;//辅助指针
        for (int i = 1; i <= nums; i++) {//使用for循环创建环形链表
            //根据编号创建小孩节点
            Boy boy = new Boy(i);
            //如果是第一个小孩
            if (i==1){
                first=boy;
                first.setNext(first);//构成一个换
                curBoy=first;//将指针指向第一个节点
            }else {
                curBoy.setNext(boy);
                boy.setNext(first);
                curBoy=boy;//指针后移
            }
        }
    }
 
 
    /*遍历环形链表*/
    public  void  showBoy(){
       /*判断链表是否为空*/
        if (first.getNext()==null){
            System.out.println("环形链表为空!!!");
            return;
        }
        Boy curBoy = first;
        while (true){
            System.out.printf("小孩的编号:%d\n",curBoy.getNo());
           if (curBoy.getNext()==first){//遍历完毕
               break;
           }
           curBoy=curBoy.getNext();//指针后移
        }
 
    }
 
 
    /*根据用户的输入计算出小孩出圈的顺序*/
/**
 *
 * @description:TODO
 * @params:1.第几个小孩开始2.表示数几下,3.最初有多少个小孩
 * @return:
 * @author: sxw
 * @time: 2020/3/11 20:32
 */
    public void countBoy(int startNo,int countNum,int nums){
        //参数校验
        if (first == null||startNo<0||startNo>nums){
            System.out.println("输入参数有误,请重新输入");
            return;
        }
        Boy helper = first;
        while (true){//将指针指向最后一个节点
            if (helper.getNext()==first){
                break;
            }
            helper=helper.getNext();
        }
        //小孩报数,将first和helper移动K-1次
        for (int i = 0; i <startNo-1 ; i++) {
            first=first.getNext();
            helper=helper.getNext();
        }
        //报数时将first和helper同时移动m-1次,然后出圈
        //当圈内只有一个节点时循环结束
        while (true){
            if (helper==first){//什么时候结束圈内只有一个节点
                break;
            }
            //让first和helper同时移动countNum次
            for (int i = 0; i <countNum-1 ; i++) {
                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());
 
    }
 
}

 3.进行测试 

1
2
3
4
5
6
7
8
9
10
11
public class JosepFu {
    public static void main(String[] args) {
        //测试构建和遍历环形链表是否ok
        CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
        circleSingleLinkedList.addBoy(5);
        circleSingleLinkedList.showBoy();
        /*测试小孩出圈*/
        circleSingleLinkedList.countBoy(1,2,5);
 
    }
}

  

 

posted @   苏先生139  阅读(535)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示