【数据结构】Python实现循环单链表+约瑟夫环举例

Python实现循环单链表就是在链表的基础上,使得尾节点的next指针指向头结点,因此在代码上和单链表有着一定的相似之处。

单链表实现icon-default.png?t=M4ADhttps://blog.csdn.net/weihuan2323/article/details/124673571

首先我们还是要先定义一个node类,用于存放链表中的节点

class Node():
    """节点"""

    def __init__(self, data):
        self.data = data
        self.next = None

有了node类,我们便可以以它为基础构建循环单链表。

对该循环单链表我定义了如下几个函数:

  • isEmpty()
  • length()
  • show()
  • add()
  • append()
  • insert()
  • remove()
  • search()
  • locate()

具体作用有注释介绍

class CircularLinkedlist():
    """单向循环链表"""

    def __init__(self):
        self.head = None

    def isEmpty(self):
        """判断链表是否为空"""
        return self.head == None

    def length(self):
        """返回链表的长度"""
        # 如果链表为空,返回长度0
        if self.isEmpty():
            return 0
        count = 1
        cur = self.head
        while cur.next != self.head:
            count += 1
            cur = cur.next
        return count

    def show(self):
        """遍历链表"""
        if self.isEmpty():
            return " "
        cur = self.head
        result = "head" + "-->" + str(cur.data)
        while cur.next != self.head:
            cur = cur.next
            data = cur.data
            result = result + "-->" + str(data)
            
        return result
            
    def add(self, data):
        """头部添加节点"""
        node = Node(data)
        if self.isEmpty():
            self.head = node
            node.next = self.head
        else:
            # 添加的节点指向head
            node.next = self.head
            # 移到链表尾部,将尾部节点的next指向node
            cur = self.head
            while cur.next != self.head:
                cur = cur.next
            cur.next = node
            # head指向添加node的
            self.head = node

    def append(self, data):
        """尾部添加节点"""
        node = Node(data)
        if self.isEmpty():
            self.head = node
            node.next = self.head
        else:
            # 移到链表尾部
            cur = self.head
            while cur.next != self.head:
                cur = cur.next
            # 将尾节点指向node
            cur.next = node
            # 将node指向头节点head
            node.next = self.head

    def insert(self, index, data):
        """在指定位置添加节点"""
        # 小于0在头部添加
        if index <= 0:
            self.add(data)
        # 大于长度在尾部添加
        elif index > (self.length() - 1):
            self.append(data)
        else:
            node = Node(data)
            cur = self.head
            count = 0
            # 移动到指定位置的前一个位置
            while count < (index - 1):
                count += 1
                cur = cur.next
            node.next = cur.next
            cur.next = node

    def remove(self, data):
        """删除一个节点"""
        # 若链表为空,则直接返回
        if self.isEmpty():
            raise IndexError("链表为空,删除失败")
        # 将cur指向头节点
        cur = self.head
        pre = None
        # 若头节点的元素就是要查找的元素data
        if cur.data == data:
            # 如果链表不止一个节点
            if cur.next != self.head:
                # 先找到尾节点,将尾节点的next指向第二个节点
                while cur.next != self.head:
                    cur = cur.next
                # cur指向了尾节点
                cur.next = self.head.next
                self.head = self.head.next
            else:
                # 链表只有一个节点
                self.head = None
        else:
            pre = self.head
            # 第一个节点不是要删除的
            while cur.next != self.head:
                # 找到了要删除的元素
                if cur.data == data:
                    # 删除
                    pre.next = cur.next
                    return
                else:
                    pre = cur
                    cur = cur.next
            # cur 指向尾节点
            if cur.data == data:
                # 尾部删除
                pre.next = cur.next

    def search(self, data):
        """查找节点是否存在"""
        if self.isEmpty():
            return False
        cur = self.head
        if cur.data == data:
            return True
        while cur.next != self.head:
            cur = cur.next
            if cur.data == data:
                return True
        return False
    
    def locate(self,index):
        '''找到索引位置为index的node'''
        if self.isEmpty():
            raise IndexError("链表为空")
        p = self.head
        j = 0
        while (p != None and j < index):
            j += 1
            p = p.next
        if (j == index):
            return p
        else:
            return None

定义完成循环单链表,那我们便可以尝试解决一下约瑟夫环问题。相较于线性表来说,使用循环单链表会相对简单一些。

约瑟夫环(Josephus):设n个人围坐在一个圆桌周围,现在从第s个人开始报数,数到第m个人,让他出局;然后从出局的下一个人重新开始报数,数到第m个人,再让他出局,……,如此反复直到所有的人全部出局为止。要解决的Josephus问题是:对于任意给定的n, s m,求出这n 个人的出局序列。

if __name__ == "__main__":
    print("循环单链表约瑟夫环".center(40,'-'))
    n = int(input("请输入总人数:"))
    s = int(input("请输入从第几个人开始报数:"))
    m = int(input("请输入数到第几个人出局:"))
    mylinklist = CircularLinkedlist()
    for i in range(1, n+1):
        mylinklist.append(i)
    result = []
    count = 1
    cur = mylinklist.locate(s-1)      

    while cur != cur.next :
        cur = cur.next
        count += 1
        if count == m:
            result.append(cur.data)
            mylinklist.remove(cur.data)
            count = 0
    
    #往结果中加入剩下的头结点    
    result.append(mylinklist.head.data)  
    print(f"\n死亡顺序为:{result}")

  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是循环单链表约瑟夫环Python 实现: ```python class Node: def __init__(self, data): self.data = data self.next = None class CircularLinkedList: def __init__(self): self.head = None def append(self, data): new_node = Node(data) if not self.head: self.head = new_node new_node.next = self.head else: current = self.head while current.next != self.head: current = current.next current.next = new_node new_node.next = self.head def remove(self, node): if self.head == node: current = self.head while current.next != self.head: current = current.next current.next = self.head.next self.head = self.head.next else: current = self.head while current.next != self.head: if current.next == node: current.next = node.next break current = current.next def __len__(self): count = 0 current = self.head while current: count += 1 current = current.next if current == self.head: break return count def josephus(circle, step): current = circle.head while len(circle) > 1: for i in range(step - 1): current = current.next circle.remove(current) current = current.next return circle.head.data # 示例 circle = CircularLinkedList() circle.append(1) circle.append(2) circle.append(3) circle.append(4) circle.append(5) print(josephus(circle, 2)) # 输出 3 ``` 在此示例中,我们首先定义了一个 `Node` 类和一个循环单链表 `CircularLinkedList` 类。`Node` 类用于表示链表中的一个节点,而 `CircularLinkedList` 类则用于表示整个循环单链表。在 `CircularLinkedList` 类中,我们实现了 `append` 方法用于向链表中添加节点,`remove` 方法用于从链表中删除节点,以及 `__len__` 方法用于获取链表中节点的数量。 接着,我们定义了一个 `josephus` 函数来模拟约瑟夫环。该函数接受两个参数:一个循环单链表 `circle` 和一个步长 `step`。在函数中,我们首先将当前节点指向链表的头节点。然后,我们进入一个循环,直到链表中只剩下一个节点为止。在每次循环中,我们先将当前节点向前移动 `step - 1` 步,然后将当前节点所指向的节点从链表中删除。最后,我们将当前节点指向下一个节点,并继续进行下一轮循环。 最后,我们在示例中创建了一个循环单链表,然后调用 `josephus` 函数来模拟约瑟夫环。在此示例中,我们设定步长为 2,因此最终输出的结果应该是第三个节点的值,即 3。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值