11、java环形单链表解决约瑟夫问题

环形单向链表:守卫连接的一个单向链表,每个节点中有其变量和一个指针指向下一个节点。头节点可有可无,此处写的没有头节点。

创建,先创建一个没有数据的first节点表示整个链表的第一个节点

添加,此处的添加与之前的不同,这里的每个节点比较简单且无顺序可言,可直接生成环形链表而非和之前一样一个个添加。所以此处传入函数的参数为节点个数,用for循环生成循环单链表。其中生成第一个节点时需要把first节点的数据替换掉,因此在i=1的时候需要额外判断一步将生成的新节点替换掉first中的无数据。并将next连到自己身上,并将temp赋值first。其他的节点只需生成新节点后将其赋值给temp的next并将新节点的next连到第一个节点即可,最后也要将temp后移、

 public void add(int n){
        if(n<2){
            System.out.println("人数太少");
            return;
        }
        Boy temp=null;
        for (int i=1;i<=n;i++){

            Boy boy=new Boy(i);
            if(i==1){
                first=boy;
                first.next=first;
                temp=first;
            }else {
                temp.next=boy;
                boy.next=first;
                temp=temp.next;
            }
        }
    }

 

遍历,判断链表不为空后利用辅助节点等于first开始不断后移遍历,辅助节点为最后一个时结束遍历

其中,辅助节点temp.next=first时temp为最后一个节点,first,next=null时链表为空

    public void list(){
        if(first.next==null){
            System.out.println("链表为空");
        }
        Boy temp=first;
        while (true){
            System.out.println(temp.no);
            if(temp.next==first) break;
            temp=temp.next;
        }
    }

 

Josephu(约瑟夫、约瑟夫环)问题

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

 

思路:设置一个helper变量,指向first的后一个即链表的最后一个节点。helper节点用while函数使其指向链表中的最后一个节点,即当其next为first时它为最后一个节点。

因为要从编号n开始数,数k下,所以这个函数需要的参数有startno(开始报数的编号)、countnum(报的数字)、nums(总的节点数)

需要在最开始检查几个变量的合理性,我自己写的时候虽然不影响整体结果但漏考虑了几种条件。老师此处的判断有如下几个:链表为空,开始编号小于1,开始编号大于总数

先将helper和first共同后移countnum-1个,让first到达开始报数的位置,接下来的程序都是重复的程序,不断找出一个个节点将其踢出链表。所以此处用一个while函数编写,其中包含了几个步骤:

1、设置跳出函数的判断条件,当链表中只剩一个节点时,跳出while循环,即first=helper时跳出循环。

2、以for循环不断报数,让helper和first后移countnum个,此时first指的节点便为要踢出链表的节点。这里我们让first再往后移一次,则现在要删除的节点位于helper和first之间,此时让first与helper连起来即可。

代码如下:

public void count(int startNo,int countNum,int nums){
        if(nums<1||nums<startNo||first==null||startNo<1){
            System.out.println("数据输入有误");
            return;
        }
        Boy helper=first;
        while (true){
            if(helper.next==first) break;
            helper=helper.next;
        }
        for (int i=0;i<startNo-1;i++){
            helper=helper.next;
            first=first.next;
        }
        while(true){
            if(first==helper){
                break;
            }
            for (int i=0;i<countNum-1;i++){
                helper=helper.next;
                first=first.next;
            }
            System.out.println(helper.next.no);
            first=first.next;
            helper.next=first;

        }
        System.out.println(first.no);
    }

其实这个问题并不难,用数组等方法也可以轻松做出来。但以此方法一个是了解了链表中的环形链表的结构和创建方式,另一个也是学到了其的应用。

 

 

 

posted @ 2022-03-25 00:25  水煮小白菜  阅读(44)  评论(0编辑  收藏  举报