不带头结点的单向循环链表的示意图
循环链表的应用场景【约瑟夫问题】
现假设 n = 5(一共有 5 个人),k = 1(从第 1 个人开始报数), m = 2(数 2 下),则出队编号的序列为:2 -> 4 -> 1 -> 5 -> 3
创建单向循环链表
代码实现:
# 创建一个 Node 类,表示一个节点
class Node:next = None # 指向下一个节点def __init__(self, no: int):self.no = no# 创建一个单向循环链表
class SingleCircleLinkedList:first = None # 指向循环链表的第一个节点,初始为空def add(self, node: Node):if not self.first:# 如果添加的是第一个节点self.first = nodenode.next = self.firstelse:temp = self.firstwhile temp.next != self.first:temp = temp.next# 找到了循环链表的最后一个节点temp.next = nodenode.next = self.first# 遍历循环链表def for_single_circle_linked_list(self):# 判断链表是否为空if not self.first:print("链表为空...")returntemp = self.firstwhile True:end = " -> " if temp.next != self.first else ""print(temp.no, end=end)temp = temp.nextif temp == self.first:breakprint()# num 为环形链表的节点个数
def test_single_circle_linked_list(num):scll = SingleCircleLinkedList()for i in range(num):scll.add(Node(i + 1))scll.for_single_circle_linked_list()test_single_circle_linked_list(5)
约瑟夫问题思路分析及代码实现
约瑟夫问题的代码实现
# 约瑟夫问题的代码实现
# 根据用户输入,计算节点出圈顺序
def josepfu(n: int, m: int, k: int):"""现假设 n = 5(一共有 5 个人)k = 1(从第 1 个人开始报数)m = 2(数 2 下)则出队编号的序列为:2 -> 4 -> 1 -> 5 -> 3"""# 校验数据if k < 1 or k > n:print("输入有误!")return# 1、创建循环链表s = SingleCircleLinkedList()# 2、向循环链表中添加 n 个节点for i in range(n):s.add(Node(i + 1))# 3、找到要开始报数的节点的前一个节点pre = Nonetemp = s.firstwhile True:if temp.next.no == k:# nonlocal prepre = tempbreaktemp = temp.next# 4、first 指向要报数的节点, pre 指向要报数的前一个节点first = pre.nextprint("出圈顺序为:")while first != pre:# 5、让 first 报数 m 次,即让 first 和 pre 移动 m - 1 次for i in range(m - 1):pre = pre.nextfirst = first.next# 6、当 first 指向的节点出圈print(first, end=" -> ")first = first.nextpre.next = firstprint(first)josepfu(5, 2, 1)
josepfu(125, 20, 10)