约瑟夫(JosePhus)问题:通过面向对象的方式创建一个循环链表来解决(内附pyhon代码)

首先介绍一下约瑟夫问题:假设有n个人围坐一圈,现要求从第1个人开始报数,报到第m个数的人退出圈。然后,从下一个人开始继续报数并按同样规则退出,直至所有人退出。要求按序输出各出列人的编号。

一、创建一个循环链表

1.1创建一个结点

这个结点有两个属性:

一个是存储数字data

一个是存储下一个结点的地址

class LNode(object):
    def __init__(self, data, next_=None):
        self.data = data
        self.next = next_

1.2通过这个结点创建一个循环链表

它需要具备以下几个功能:

增加、删除、打印

class CycleLink(object):
    def __init__(self):
        self.head = None
        self.num = 0

    # 尾插法 
    def append(self, i):##插入1个元素的函数
        if self.head == None:
            self.head = LNode(i)
            self.head.next = self.head
            self.num = self.num+1
            return
        p = self.head
        while p.next != self.head:  # 使得p指向尾结点
            p = p.next
        p.next = LNode(i)
        p.next.next = self.head
        self.num = self.num+1

    def appends(self, arr):##后期可以插入列表里面的数,这个可以单独写一个函数放在外面
        for i in range(len(arr)):
            self.append(arr[i])

    def delete(self, node):  # 删除动作,并输出删掉的序号
        p = self.head
        if node == p:  # 如果删除头结点,让头结点向后移动
            self.head = p.next
        while p.next != node:  # 找到指定结点的前一个结点
            p = p.next
        p.next = node.next
        self.num -= 1
        print(node.data)

    def printall(self):  # 将循环链表的打印
        p = self.head
        while p.next != self.head:  # 防止一直循环,打印到尾结点结束
            print(p.data, end=' ')
            p = p.next
        print(p.data, end=' ')

二、利用这个循环链表模拟人不断离开的过程

la = CycleLink()
n, m = 10, 2##这里我们假设一共十个人,每次删去第二个人
a = [i for i in range(1, n+1)]
la.appends(a)#利用了链表中的增方法
p = la.head##开始删人
while p.next != la.head:#我们要先找到尾结点,从尾结点开始数,因为从头结点开始数到2是第三个人了
    p = p.next
while la.num > 0:#循环终止的条件是这个圈里没有人了
    for i in range(m):
        p = p.next
    la.delete(p)

好啦,以上三段代码就可以啦。

有什么可以更好优化的地方,我们评论区探讨~

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值