约瑟夫环问题
已知 n 个人(分别用编号 1,2,3,…,n 表示)围坐在一张圆桌周围,从编号为 k 的人开始顺时针报数,数到 m 的那个人出列;他的下一个人又从 1 开始,还是顺时针开始报数,数到 m 的那个人又出列;依次重复下去,直到圆桌上剩余一个人。
如下图所示,假设此时圆周周围有 5 个人,要求从编号为 3 的人开始顺时针数数,数到 2 的那个人出列:
出列顺序依次为:
- 编号为 3 的人开始数 1,然后 4 数 2,所以 4 先出列;
- 4 出列后,从 5 开始数 1,1 数 2,所以 1 出列;
- 1 出列后,从 2 开始数 1,3 数 2,所以 3 出列;
- 3 出列后,从 5 开始数 1,2 数 2,所以 2 出列;
- 最后只剩下 5 自己,所以 5 胜出。
C语言实现
代码:
#include <stdio.h>
#include <stdlib.h>
//循环链表结构体
typedef struct node{
int num;
struct node *next;
}person;
person *ring_init(int n);
person *del_person(person *head, int m);
//初始化循环链表,并返回其头指针
person *ring_init(int n)
{
person *head = (person *)malloc(sizeof(person));
head->num = 1;
head->next = NULL;
person *temp = head;
for(int i=2; i<=n; i++)
{
person *body = (person *)malloc(sizeof(person));
body->num = i;
body->next = NULL;
temp->next = body;
temp = body;
}
temp->next = head;
return head;
}
//删除从头指针指向的结点数到m的结点,并打印其编号
person *del_person(person *head, int m)
{
person *prior = head;
person *temp = NULL;
for(int i=0; i<m-2; i++)
{
prior = prior->next;
}
temp = prior->next;
prior->next = temp->next;
printf("出列人的编号是:%d\n", temp->num);
free(temp);
return prior->next;
}
//主函数
void main()
{
int n, m, k;
printf("请输入约瑟夫环的人数:\nn = ");
scanf("%d", &n);
printf("请输入开始报数人的编号:\nk = ");
scanf("%d", &k);
printf("请输入报数的大小:\nm = ");
scanf("%d", &m);
person *head = ring_init(n);
for(int i=0; i<k-1; i++) //将开始报数的人重新设置为头指针指向的结点
{
head = head->next;
}
while(n>1)
{
head = del_person(head, m);
n--;
}
printf("最后留下人的编号是:%d\n", head->num);
//打印日期和时间
system("date /T");
system("TIME /T");
system("pause");
exit(0);
}
运行结果:
Python实现
代码:
import datetime
import time
//结点类
class Node:
def __init__(self, num):
self._num = num
self._next = None
//约瑟夫环类
class Joseph_Ring:
def __init__(self, head=None):
self._head = head
//创造约瑟夫环
def creat(self, n):
self._head = Node(1)
temp = self._head
i = 2
while i <= n:
body = Node(i)
temp._next = body
temp = body
i += 1
temp._next = self._head
//头结点移到开始报数人的结点
def start(self, k):
i = 1
while i < k:
self._head = self._head._next
i +=1
//删除出列人的结点,并打印其编号,然后将头结点移至下一个人的结点
def dele(self, m):
prior = self._head
i = 0
while i < m-2:
prior = prior._next
i += 1
temp = prior._next
self._head = temp._next
prior._next = self._head
print("出列人的编号是:{}".format(temp._num))
del temp
if __name__ == '__main__':
ring = Joseph_Ring()
n = int(input("请输入约瑟夫环的人数:\nn = "))
ring.creat(n)
k = int(input("请输入开始报数人的编号:\nk = "))
ring.start(k)
m = int(input("请输入报数的大小:\nm = "))
i = 0
while i < n-1:
ring.dele(m)
i += 1
print("最后留下人的编号是:{}".format(ring._head._num))
//打印日期和时间
datetime = datetime.datetime.now()
print(datetime.strftime("%Y-%m-%d\n%H:%M:%S"))