Josephu报数问题

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

创建节点

package com.m.demo5;

public class Node {
	public int id;
	public Node next;
	public Node(int id) {
		
		this.id = id;
	}
	@Override
	public String toString() {
		return "Node [id=" + id + "]";
	}
	
}

Josephu类

package com.m.demo5;

public class Josephu {
	Node first=null;//标记第一个位置,后续不会移动,所以需要一个temp
	//创建一个num大小的约瑟夫环
	public void createJosephu(int num) {
		Node temp=first;
		if(num<1) {
			System.out.println("输入不符合");
			return;
		}
		for(int i=1;i<=num;i++) {
			Node n=new Node(i);
//			System.out.println(n);
			if(i==1) {//创建第一个环,第一个数的时候,让first指向自己
				first=n;//先创建第一节点,然后让temp辅助操作
				first.next=first;
				temp=first;
			}else {//其他时候,让temp移动连接
				temp.next=n;
				n.next=first;
				temp=n;
				
			}
		}
	}
	
//	显示约瑟夫环
	public void show() {
		Node temp=first;
		if(temp==null) {
			System.out.println("没有节点");
			return;
		}
		while(true) {
			System.out.println(temp);
			
			if(temp.next==first) {//遇到最后一个节点的时候就退出循环了,所以将打印写在最前面,防止最后一个节点漏打
				break;
			}
			temp=temp.next;
		}
		
	}
//	创建出队
	/**
	 * 需要一个temp节点一直在first节点的前一个,做为环的最后一个
	 * @param startIndex 从第几个节点开始,也就是第几个节点作为first节点 需要通过这个来移动first节点的位置
	 * @param m 表示节点报的数 移动m-1个,first指向的节点出队
	 * @param nums 表示约瑟夫环的大小,用来初始化判断输入
	 */
	public void outQueueJosep(int startIndex,int m,int nums) {
		if(first==null) {
			System.out.println("空环");
			return;
		}
		if(startIndex>nums||startIndex<1) {
			System.out.println("输入的参数不对");
			return;
		}
		//确定first的位置
		for(int i=0;i<startIndex-1;i++) {
			first=first.next;
		}
//		确定在这个情况下,环最后的一个节点 temp;
		Node temp=first;
		while(true) {
			if(temp.next==first) {
				break;
			}
			temp=temp.next;
		}
//		开始出队
		while(true) {
			if(temp==first) {//当temp==first的时候,说明环中只有一个节点了
				break;
			}
//			通过报的数开始移动temp和first,first指向的出队
			for(int i=0;i<m-1;i++) {//m-1:因为节点本身要报数
				first=first.next;
				temp=temp.next;
			}
			
			System.out.println(first);
			first=first.next;
			temp.next=first;
		}
		System.out.println(temp);
		
		
		
	}
}

测试类

package com.m.demo5;

public class test {
	public static void main(String[] args) {
		Josephu j=new Josephu();
		j.createJosephu(5);
		j.show();
		System.out.println("=========");
		j.outQueueJosep(1, 2, 5);
	}
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用单向循环链表实现约瑟夫问题的C++代码: ``` #include <iostream> using namespace std; // 定义单向循环链表结点结构体 struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(nullptr) {} }; // 约瑟夫问题求解函数 void josephu(int n, int m) { // 构造循环链表 ListNode* head = new ListNode(1); ListNode* p = head; for (int i = 2; i <= n; i++) { p->next = new ListNode(i); p = p->next; } p->next = head; // 将链表尾部连接到头部,形成循环链表 // 模拟约瑟夫问题的求解过程 p = head; while (p->next != p) { // 当链表中只剩一个结点时停止 for (int i = 1; i < m; i++) { p = p->next; // 找到要删除的结点的前一个结点 } ListNode* del = p->next; // 要删除的结点 p->next = del->next; // 将要删除的结点从链表中删除 cout << del->val << " "; // 输出删除的结点的值 delete del; // 释放被删除结点的内存空间 } cout << p->val << endl; // 输出最后剩下的结点的值 delete p; // 释放最后剩下的结点的内存空间 } int main() { int n, m; cout << "请输入总人数n和报数m:"; cin >> n >> m; josephu(n, m); return 0; } ``` 在上述代码中,我们首先构造了一个包含1~n的单向循环链表,然后模拟了约瑟夫问题的求解过程。具体来说,我们用一个指针p来遍历链表,每次找到要删除的结点的前一个结点,并将要删除的结点从链表中删除,并输出其值。当链表中只剩一个结点时,即p->next==p时,算法结束,输出最后剩下的结点的值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值