python 单向循环(环形)链表

不带头结点的单向循环链表的示意图

python 单向循环(环形)链表_第1张图片

循环链表的应用场景【约瑟夫问题】

python 单向循环(环形)链表_第2张图片

 现假设 n = 5(一共有 5 个人),k = 1(从第 1 个人开始报数), m = 2(数 2 下),则出队编号的序列为:2 -> 4 -> 1 -> 5 -> 3

python 单向循环(环形)链表_第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 = node
            node.next = self.first
        else:
            temp = self.first
            while temp.next != self.first:
                temp = temp.next

            # 找到了循环链表的最后一个节点
            temp.next = node
            node.next = self.first

    # 遍历循环链表
    def for_single_circle_linked_list(self):
        # 判断链表是否为空
        if not self.first:
            print("链表为空...")
            return

        temp = self.first
        while True:
            end = " -> " if temp.next != self.first else ""
            print(temp.no, end=end)
            temp = temp.next
            if temp == self.first:
                break
        print()


# 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)

 约瑟夫问题思路分析及代码实现

python 单向循环(环形)链表_第4张图片

约瑟夫问题的代码实现

# 约瑟夫问题的代码实现
# 根据用户输入,计算节点出圈顺序
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 = None
    temp = s.first
    while True:
        if temp.next.no == k:
            # nonlocal pre
            pre = temp
            break
        temp = temp.next

    # 4、first 指向要报数的节点, pre 指向要报数的前一个节点
    first = pre.next

    print("出圈顺序为:")
    while first != pre:
        # 5、让 first 报数 m 次,即让 first 和 pre 移动 m - 1 次
        for i in range(m - 1):
            pre = pre.next
            first = first.next

        # 6、当 first 指向的节点出圈
        print(first, end=" -> ")
        first = first.next
        pre.next = first
    print(first)


josepfu(5, 2, 1)
josepfu(125, 20, 10)

你可能感兴趣的:(数据结构和算法,python,数据结构,链表)