约瑟夫问题代码及执行过程图解

文章介绍了约瑟夫问题的背景及一个基于Python的实现方法。使用无头结点的单向循环链表来存储小孩,通过一个指针跟踪报数,当报到M时删除该节点,然后继续循环,直到所有小孩都出局。代码详细展示了如何创建链表、删除节点以及遍历过程。
摘要由CSDN通过智能技术生成
约瑟夫问题是个有名的问题:N个小孩围成一圈,从第一个开始报数,第M个将出局,然后从出局的那个孩子的下一个重新开始报数,每个人依次出局。
例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3,1。

具体实现思路如下:

建立一个没有头结点的单向循环链表,用于存放所有小孩。

因为每次出局一个人后,下一个人要重新从1开始报数。所以设置一个指针专门指向第一个报数的人。

因为每次没轮到报M的小孩,每个小孩报的数就会递增,所以用while循环<m-1作为条件,结束这个循环就一位着一个小孩要出局。

出局就是删除结点的操作。

具体代码如下:

#约瑟夫问题
#约瑟夫问题是个有名的问题:N个小孩围成一圈,从第一个开始报数,第M个将出局,然后从出局的那个孩子的下一个重新开始报数
# 例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3,1.
#要用不带头结点的循环链表存放所有人
class Child:#结点类型
    def __init__(self.nol):
        self.no=nol
        self.next=None

class Joseph:
    def __init__(self,n1,m1):
        self.n=n1
        self.m=m1
        self.first=Child(1)#设置第一个结点
        t=self.first#t始终指向头结点,便于最后形成环,便于引用标记
        for i in range(2,self.n+1):
            p=Child(i)
            t.next=p
            t=p#指针移动到下一位
        t.next=self.first#最后一个结点的next域指向头结点,形成环
#出局就代表这个结点被删除,然后重新开始报数
    def Jsequence(self):
        for i in range(1,self.n+1):#最终,所有人都将出局,也就是每次循环都将出局一人
            p=self.first#设置一个指针,标志每次循环开始的位置,并且每次循环结束删除一个结点之后都要重置first结点
            j=1#j用来判断报数出局的那个人
            while j<self.m-1:#j<self.m-1表示话没有轮到那个人,j就要+1,并且指针也要后移一位
                j+=1
                p=p.next
            #退出循环表示下一个就是要退出的那个人
            q=p.next#标记要退出的那个人
            print(q.no,end='')#输出要退出的那个人
            p.next=q.next#单链表的删除操作
            self.first=p.next#重置first,再进行下一次循环
        print()

n=6
m=3
L=Joseph(n.m)
print("n=%d,m=%d的约瑟夫序列"%(n,m))
L.Jsequence()

具体代码执行图解如下:

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

踏歌~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值