实现约瑟夫环形链表

题目

41个人排成一个圆圈,由第1个人 开始报数,每报数到第3人,该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。约瑟夫与朋友在第16与第31个位置,于是活了下来。请用单向环形链表描述该结构并呈现整个自杀过程。

设计

  • 首先要设计一个节点模型
     class Node {
        int value;
        Node next;
        Node(int value) {
            this.value = value;
        }
     }
  • 遍历并用 last 节点做成一个单向线性的链表,之后将自身的初始节点指向last.next 节点,扣成一个环
    Node head = new Node(1);
    Node last = head;
    /** 一条单链数据 */

     for (int i = 2; i <= n; i++) {
            last = (last.next = new Node(i));
    }

   /**
   回调指向,形成环形链,可用如下代码做环形链表是否形成的测试
    System.out.println(last.next.next.value);
   */
    last.next = head;
  • 遍历每个报数到m(m=3)的节点,并重组链表
    for (int i = 1; i < m; i++) {
        last = last.next; //6
    }
    /**首先以总人数3为例,再以6为例推测这段代码,以及结合for循环就很好理解了*/
     last.next = last.next.next; //3、4、5
  • 整个自杀链表遍历的结束条件
    /**
    以总人数 3 为例 last.next 经过遍历为3时赋值给 last ,
    此时 last==last.next 是成立的,即可跳出while循环
    */
    while (last != last.next) {
        for (int i = 1; i < m; i++) {
           last = last.next;
        }
        last.next = last.next.next;
  }

实现

import org.junit.Test;
import static java.lang.System.out;

/**
 * @author lorem
 */
public class NodeNodeNext {
    class Node {
        int value;
        Node next;
        Node(int value) {
            this.value = value;
        }
    }

    @Test
    public void test() {
        winner(41, 3);
    }

    void winner(int n, int m) {
        Node head = new Node(1);
        Node last = head;
        /** 一条单链数据 */
        for (int i = 2; i <= n; i++) {
            last = (last.next = new Node(i));
        }
        /**回调指向,形成环形链*/
        last.next = head;
        out.println("依次死亡的序号:");
        while (last.value != last.next.value) {
            for (int i = 1; i < m; i++) {
                last = last.next;
            }
            out.print(last.next.value + " ");
            last.next = last.next.next;
        }
        out.println("\n" + "最后存活的序号:");
        out.printf("%d", last.value);
    }
}

原文地址:https://www.cnblogs.com/loremwalker/p/9693633.html

时间: 2024-07-29 13:12:16

实现约瑟夫环形链表的相关文章

php实现单,双向链表,环形链表解决约瑟夫问题

传智播客PHP学院 韩顺平 PHP程序员玩转算法第一季  http://php.itcast.cn 聊天篇: 数学对我们编程来说,重不重要? 看你站在什么样的层次来说. 如果你应用程序开发,对数学要求不高 但是,如果你开发系统软件,比如(搜索/识别软件[图像,语言识别]/操作系统...)对数学高 建模.大量数学模型. 老师啊啊.我是学C++的.麻烦,谈哈对QT和MFC的看法嘛.前景什么的, 记住 : 打好基础,大有可为! 初中毕业能去传智学习吗? 学习It, 不管是java ,php ,c#,对

java 环形链表实现约瑟夫(Joseph)问题

约瑟夫问题又名丢手绢问题.相传著名犹太历史学家 Josephus 利用其规则躲过了一场自杀游戏,而后投降了罗马. 问题: 已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.* 从编号为k的人开始报数,数到m的那个人出列:* 他的下一个人又从1开始报数,数到m的那个人又出列:* 依此规律重复下去,直到圆桌周围的人全部出列. 用节点来模拟游戏中的人,用链表来表示游戏中的人按一定的顺序排列.每一个节点给一个编号,从编号为k的节点开始计数,计到m的节点从链表中退出.之后m的下一个节点从新

双向链表和环形链表(约瑟夫问题)

双向链表 package linkedlist; public class DooubleLinkedListDemo { public static void main(String[] args) { HeroNode2 hero1 = new HeroNode2(1,"宋江","及时雨"); HeroNode2 hero2 = new HeroNode2(2,"卢俊义","玉麒麟"); HeroNode2 hero3 =

Java数据结构之单向环形链表(解决Josephu约瑟夫环问题)

1.Josephu(约瑟夫.约瑟夫环)问题: 设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列. 提示: 用一个不带头结点的循环链表来处理Josephu 问题:先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除算法

约瑟夫问题 环形链表及递归

//--------------------环形链表 //#include <windows.h> //#include <iostream> //using namespace std; // //#define R 40//人数 //#define N 4//每隔多少删去一个节点 // //struct node //{ // int id; // node *next; //}; // //void initCircle(node *phead, int num) //{ /

环形链表与约瑟夫环问题

思路: 代码: public class Josepfu { public static void main(String[] args) { // 测试一把看看构建环形链表,和遍历是否ok CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList(); circleSingleLinkedList.addBoy(125);// 加入5个小孩节点 circleSingleLinkedList.showBo

C# 数据结构 - 单链表 双链表 环形链表

链表特点(单链表 双链表) 优点:插入和删除非常快.因为单链表只需要修改Next指向的节点,双链表只需要指向Next和Prev的节点就可以完成插入和删除操作. 缺点:当需要查找某一个节点的时候就需要一个节点一个节点去访问,这样所花的时候就比较多了.(顺序表可以弥补这缺点,但插入和删除就非常耗性能) 单链表 单链表的构成:必须要有一个链表头(head),每个节点里面有一个Next用于指向下一个节点(类似于指针).最后一个节点的Next为null来标识链表的尾. 如下图 代码实现 1 /* ----

单向环形链表

单向环形链表(Josepfu) 约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)按顺时针方向围坐在一张圆桌周围,每个人持有一个密码(正整数).一开始任选一个整数作为报数上限值m,从第一个人开始顺时针自1报数,报到m时停止报数,报m的那个人出列,他的密码作为新的m值,从他在顺时针方向上的下一个人又开始重新从1报数,报到m的那个人出列又出列:依此规律重复下去,直到圆桌周围的人全部出列 /* 约瑟夫问题 */ public class Josepfu { pu

环形链表---Java

/** * * @author Administrator * 功能:丢手帕问题 */ package com.litao; public class Demo4 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub CycLink cycLink = new CycLink(); cycLink.setLen(9); cycLink.createLin