首先介绍一下约瑟夫问题:假设有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)
好啦,以上三段代码就可以啦。
有什么可以更好优化的地方,我们评论区探讨~