• 单向环形链表


    单向环形链表介绍

    单向环形链表可以理解为单链表首尾相连的链表.

    创建环形链表

    • 构建一个单向环形链表思路
      • 先创建第一个节点,让first指向该节点,并形成环形 first.next = first
      • 添加辅助指针curBoy = first 待添加的节点为boy
      • 添加节点 curBoy.next = boy;boy.next = first;(成环) curBoy = boy;(指向下一个节点)
    • 遍历
      • 先让一个辅助针织curBoy指向first节点
      • 然后通过while循环遍历该环形链表即可,结束条件为:curBoy.next == first

    josephu问题

    设编号为1,2,3......n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,他的下一位从1开始报数,数到m的那个人又出列,以此类推,知道所有人出列为止,由此产生一个出队编号的序列.

    • 提示:用一个不带头结点的循环链表来处理josephu问题:先构建一个有n和节点的单循环链表,然后由k节点起从1开始计数,计数到m,对应节点从链表中删除,然后被删除的下一个节点又从1开始计数,知道最后一个节点从链表中删除.

    • 需要创建一个辅助指针helper,事先应该指向环形链表的最后一个节点 (遍历实现 结束条件 helper.next = first)

    • 报数前,先让first和helper移动k-1次 (这是题中的从第k个人开始报数)

    • 当小孩报数时,让first和helper指针同时移动m-1次

    • 这时就将first指向的小孩出圈.

      • first = first.next;
      • helper.next = first

    代码实现

    public class circleLinkedList {
        public static void main(String[] args) {
    
            CircleLinked circleLinked = new CircleLinked();
            // 测试添加
            circleLinked.add(5);
            circleLinked.list();
            System.out.println("测试出圈----------------");
            //测试出圈
            circleLinked.countBoy(5,1,2);
        }
    }
    
    //循环链表
    class CircleLinked{
        //第一个节点 设置为null 是因为下面会进行复制
        private Boy first = null;
    
        /**
         *
         * @param num 向环形链表添加的节点数目
         */
        public void add(int num){
            if (num < 1){
                System.out.println("输入无效数据!!");
                return;
            }
            Boy curBoy = null;  // 添加辅助指针
            for (int i = 1;i <= num;i++){
                Boy boy = new Boy(i);
                //第一个节点
                if (first == null){
                    first = boy;
                    first.setNext(first);
                    curBoy = first;  //让辅助指针指向first
                }else {
                    curBoy.setNext(boy);
                    boy.setNext(first);  //尾节点指向头结点,成环
                    curBoy = boy;  //指向下一个节点
                }
            }
        }
        //显示链表
        public void list(){
            if (first == null){
                System.out.println("链表为空!!");
                return;
            }
            Boy curBoy = first;
            while (true){
                System.out.printf("小孩编号为%d
    ",curBoy.getNo());
                if (curBoy.getNext() == first){
                    break;
                }
                curBoy = curBoy.getNext();
            }
        }
    
        /**
         *
         * @param n 总共有多少和小孩
         * @param k 从第几个人开始报数
         * @param m 数几下
         */
        public void countBoy(int n,int k,int m){
            //校验数据
            if (first == null || k < 1 || k > n){
                System.out.println("数据有误");
                return;
            }
            Boy helper = first;
            //helper指向环形链表的最后一个节点
            while (true){
                if (helper.getNext() == first){
                    break;
                }
                helper = helper.getNext();
            }
            ///小孩报数前,先让 first 和 helper 移动 k - 1 次
            for (int i = 0;i < k-1;i++){
                first = first.getNext();
                helper = helper.getNext();
            }
            while (true){
                if (helper == first){ //圈中只有一个节点
                    break;
                }
    
                //first 和 helper 移动m-1此
                for (int i = 0;i < m-1;i++){
                    first = first.getNext();
                    helper = helper.getNext();
                }
                //出圈小孩
                System.out.printf("出圈编号为%d
    ",first.getNo());
                first = first.getNext();
                helper.setNext(first);
            }
            System.out.printf("出圈编号为%d
    ",first.getNo());
        }
    }
    
    class Boy{
        private int no;
        private Boy next;
    
        public Boy(int no){
            this.no = no;
        }
        public int getNo() {
            return no;
        }
    
        public Boy getNext() {
            return next;
        }
    
        public void setNext(Boy next) {
            this.next = next;
        }
    }
    
  • 相关阅读:
    什么是web标准、可用性、可访问性
    前端面试>逻辑推理题~~
    git 安装
    wcf生成客户端代理的四种方法
    mysql 安装
    理解Linux 的处理器负载均值load averages
    高性能服务器架构
    事务日志
    Epoll工作模式详解
    事务和两阶段提交
  • 原文地址:https://www.cnblogs.com/liuzhidao/p/13795126.html
Copyright © 2020-2023  润新知