数据结构之线性表:循环链表实现约瑟夫环(C & Python)

约瑟夫环问题

已知 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")) 

运行结果:

  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

观察者555

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值