约瑟夫环问题

介绍

约瑟夫问题(有时也称为约瑟夫斯置换,是一个计算机科学和数学中的问题。在计算机编程的算法中,类似问题又称为约瑟夫环。又称“丢手绢问题”.)

image

打印所有人死的顺序

C语言代码实现:

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

/**
   循环链表实现约瑟夫环
   41个人排成一个圆圈,然后从1-3报数,报到3的人自杀,依次类推,直到剩下最后两个人可以存活下来,这两个人分别是第16个位置和第31个位置
*/

/*
定义node节点
*/
typedef struct node{
      int data;
      node * next;
}node, *Node;

/*
初始化循环链表
*/
node * init_list(int n){
      // 声明头指针
      Node head;
      // 声明尾指针
      Node tail;
      head = (Node)malloc(sizeof(node));
      // 让当前尾指针指向头节点
      tail = head;
      int i = 1;
      while (i <= n) {
      	  Node newNode = (Node)malloc(sizeof(node));
      	  if (newNode == NULL){
              // 退出程序
      	      exit(0);
      	  }
	  newNode->data = i++;
          tail->next = newNode;
          tail = newNode;
      }

      // 让尾节点的指针域指向第一个节点
      tail->next = head->next;
      // 删除头节点,释放内存
      free(head);
      // 返回第一个节点的指针
      return tail->next;
}

// 主函数
int main(){
      Node ysfh;
      int people;
      int num;

      printf("请输入参与约瑟夫环游戏的人数:");
      scanf("%d", &people);
      printf("请输入报数的终点(1-n):");
      scanf("%d", &num);

      // 初始化约瑟夫环
      ysfh = init_list(people);
      // 定义一个临时指针变量
      Node p = ysfh;
      // 用于计数
      int c = 1;

      while (p != p->next){
      	  int count = 1;
      	  for (; p != p->next && count < num - 1; p = p->next) {
      	      count++;	
	  }		
	  Node temp = p->next;
	  printf("%d-->%d\n",c++, temp->data);
	  p->next = temp->next;		
          // 释放内存
	  free(temp);
          // 指向下一个节点
          p = p->next;
      }

      // 打印最后一个
      printf("%d-->%d\n",c, p->data);
      return 0;
}

运行结果:

找出最后一个活下来的人

Java语言代码实现:

import java.util.Scanner;

/**
 * @author LZP
 * @date 2021年4月15日
 * @Description
 * @version 1.0
 * 
 * 数组版
 * 
 * 找出最后一个活下来的人
 */
public class 约瑟夫环_01 {
    public static void main(String[] args) {
	Scanner input = new Scanner(System.in);
	int n = input.nextInt();
	int k = input.nextInt();
	input.close();
	int[] arr = new int[n];
	for (int i = 0; i < n; i++) {
	    arr[i] = i + 1;
	}
	
	// 记录当前人数
	int count = n;
	// 记录此时的数组下标
	int index = 0;
	int num = 0;
	while (count > 1) {
	    num++;
	    if (num == k) {
		// 重置为0
		num = 0;
		count--;
		arr[index] = 0;
	    }
	    index = (index + 1) % n;
	    while (arr[index] == 0) {
		index = (index + 1) % n;
	    }
	}
	
	for (int i = 0; i < n; i++) {
	    if (arr[i] != 0) {
		System.out.println(arr[i]);
	    }
	}
	
    }
}
posted @   没有你哪有我  阅读(141)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
点击右上角即可分享
微信分享提示