数据结构 -线性结构 ->环形链表

单向环形链表:单向链表的改变版,链表中的最后一个数永远指向链表的第一个数,由此形成一个环形。

  先自定义一个节点类:

 1 /**
 2  * 定义节点类Boy
 3  */
 4 class Boy{
 5     private int no;
 6     private Boy next;
 7     public Boy(int no){
 8         this.no = no;
 9     }
10     public int getNo(){
11         return this.no;
12     }
13     public Boy getNext(){
14         return this.next;
15     }
16     public void setNext(Boy boy){
17         this.next = boy;
18     }
19 }

  再创建一个管理节点类,实现环形链表。

 1 /**
 2  * 创建环形链表,实现Joseph
 3  */
 4 class CircleSingleLinkedList{
 5     private  Boy first = null;
 6 //创建环形链表的方法
 7     public void creat(int num){
 8         if(num < 1){
 9             System.out.println("至少输入1个数");
10             return;
11         }
12         Boy temp = first;
13         for(int i =1; i <= num;i++){
14             Boy boy = new Boy(i);//每次遍历都创建一个节点
15             //头节点
16             if(i == 1){
17                 first = boy;
18                 first.setNext(first);//形成环
19                 temp = first;//temp指向第一节点
20             }
21             temp.setNext(boy);//用temp连接下一个节点
22             boy.setNext(first);
23             temp = boy;//temp后移
24         }
25     }
26     //遍历环形链表
27     public void showList() {
28         if(first == null){
29             System.out.println("链表为空!");
30             return;
31         }
32         Boy cur = first;
33         while(true){
34             System.out.printf("编号为:%d\n",cur.getNo());
35             if(cur.getNext() == first){
36                 break;//链表循环结束
37             }
38             cur = cur.getNext();
39         }
40     }
41     //链表总数
42     public void sum() {
43         if(first == null){
44             System.out.println("链表为空!");
45             return;
46         }
47         Boy cur = first;
48         int count = 0;
49         while(true){
50             count += 1;
51             if(cur.getNext() == first){
52                 break;//链表循环结束
53             }
54             cur = cur.getNext();
55         }
56         System.out.printf("链表中总数:%d\n",count);
57     }
58 }

通过环形链表可以实现约瑟夫问题:

  指定一个临时变量始终指向环形链表第一个数的前一个节点,单到了约定要出圈的节点时,first节点移动到下一个节点,零时变量的next域直接指向移动完的first,则移动前的first节点没有指引就会被jvm垃圾回收机制直接回收。

 1  /**
 2      * @param startNo 从第k个数开始数
 3      * @param countNo 到第m个数出圈
 4      */
 5     public void out(int startNo,int countNo,int sum){
 6         if(first == null || startNo > sum || startNo < 0){
 7             System.out.println("输入数据有误!");
 8             return;
 9         }
10         Boy cur = first;
11         //cur指向first的前一个数
12         while(true){
13             if(cur.getNext() == first){
14                 break;
15             }
16             cur = cur.getNext();
17         }
18         //出圈之前将first和cur移动到k-1的位置
19         for(int j = 0 ; j < startNo-1; j++){
20             first = first.getNext();
21             cur = cur.getNext();
22         }
23         //出圈
24         System.out.print("出圈顺序: ");
25         while(true){
26             if(cur == first){
27                 break;//链表中只剩一个数
28             }
29             //移动到m-1的位置后出圈
30             for(int j = 0; j < countNo-1 ; j++){
31                 first = first.getNext();
32                 cur = cur.getNext();
33             }
34             System.out.printf("%d ——> ",first.getNo());
35             first = first.getNext();
36             cur.setNext(first);
37         }
38         System.out.print(first.getNo());
39     }

 

posted @ 2020-09-24 11:06  sixsixman  阅读(178)  评论(0)    收藏  举报