0083 环形链表
创始人
2024-04-01 20:31:44

 

 

 

package LinkedList_;

/*
 *     单向环形链表应用场景——约瑟夫问题
 *         设编号为1,2....n的n个人围成一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的人出列,
 *         它的下一位又从1开始报数,数到m的人又出列.....以此类推,直到所有人出列,产生一个出队编号序列。
 * 
 *     例如: n=5  => 总共有5个人
 *         k=1  => 从第1个人开始报数
 *         m=2  => 数2次
 *     出队编号序列为:2-->4-->1-->5-->3
 * 
 *    应用:用一个不带头结点的循环链表处理,构成一个有n个结点的循环链表,然后由k结点起从1开始计数,
 *        计到m时,删除对应的结点,然后再从下一个结点从1开始计数,直到最后一个结点从链表中删除
 *
 *     构建单向环形链表思路:
 *         1.先创建第一个结点,让first指向该结点,并形成环形
 *         2.每创建一个结点,就把该结点加入到已有的环形链表中
 * 
 *     遍历环形链表
 *         1.先让一个辅助变量temp,指向first结点
 *         2.通过while循环遍历该环形链表 当temp.next = first时结束
 * 
 *  出队编号序列
 *      1.创建一个辅助变量temp,事先应指向环形链表的最后一个结点
 *      2.报数前,让first和temp移动 k-1 次
 *      3.报数时,让first和temp同时移动 m-1 次
 *      4.让first指向的结点出队
 *          first = first.next;
 *          temp.next = first;
 *          出队结点没有任何引用,被回收
 *      
 */
public class RingLinkedList_ {
    public static void main(String[] args) {
        RingLinkedList ringLinkedList = new RingLinkedList();
        ringLinkedList.addNode(5);//加入五个结点
        ringLinkedList.showNode();//显示
        ringLinkedList.countNode(1, 2, 5);//2-->4-->1-->5-->3
        
        System.out.println("======================================");
        RingLinkedList ringLinkedList2 = new RingLinkedList();
        ringLinkedList2.addNode(38);
        ringLinkedList2.countNode(2, 4, 38);
    }
}

//创建环形单向链表
class RingLinkedList{
    //创建first结点
    public Node first = null;
    //添加结点
    public void addNode(int nums) {
        //校验
        if (nums < 1) {
            System.out.println("nums值不正确");
            return;
        }
        Node temp = null;//辅助变量,帮助遍历
        //使用for循环创建环形链表
        for (int i = 1; i <= nums; i++) {
            //根据编号创建结点
            Node node = new Node(i);
            if (i == 1) {//先创建第一个结点,让first指向该结点,并形成环形
                first = node;
                first.next = first;//构成环形
                temp = first;//让temp指向第一个编号
            }else {
                temp.next = node;
                node.next = first;
                temp = node;
            }
        }
    }
    
    //遍历(显示)
    public void showNode() {
        //判断是否为空
        if (first == null) {
            System.out.println("链表为空,没有结点");
            return;
        }
        //因为first不能动,仍使用辅助变量temp完成遍历
        Node temp = first;
        while(true) {
            System.out.printf("编号%d\n",temp.no);
            if (temp.next == first) {//遍历完毕
                break;
            }
            temp = temp.next;
        }
    }
    
    //出队序列
    //startNo表示k,从第几个开始数
    //countNum表示m,数几次
    //nums表示n,总共几人
    public void countNode(int startNo,int countNum,int nums) {
        //校验
        if (first == null || startNo < 1 || startNo > nums) {
            System.out.println("输入有误,请重新输入");
            return;
        }
        //1.创建一个辅助变量temp,事先应指向环形链表的最后一个结点
        Node temp = first;
        while(true) {
            if (temp.next == first) {//temp指向了最后结点
                break;
            }
            temp = temp.next;
        }
        //2.报数前,让first和temp移动 k-1 次
        for(int j = 0;j < startNo - 1;j++) {
            first = first.next;
            temp = temp.next;
        }
        //3.报数时,让first和temp同时移动 m-1 次
        //循环直到只有一个结点
        while(true) {
            if (temp == first ) {//只有一个结点
                break;
            }
            for(int j = 0;j < countNum - 1;j++) {
                first = first.next;
                temp = temp.next;
            }//这时first指向的结点就是要出队的结点
            System.out.printf("出队编号:%d\n",first.no);
            //4.让first指向的结点出队
            first = first.next;
            temp.next = first;
        }
        System.out.printf("最后的编号为:%d\n",first.no);
    }
}

//创建Node类,表示结点
class Node{
    public int no;//编号
    public Node next;//指向下一个结点,默认为null
    public Node(int no) {
        this.no = no;
    }
}

相关内容

热门资讯

长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...