数据结构与算法分析1.2 Python创建循环链表解决约瑟夫环问题

#创建结点类,类中有数据、指针两个对象,数据域通过输入获得,指针域默认为空
class LinkNode:
    def __init__(self, data, next=None):
        self.data = data
        self.next = next

#创建链表类,创建默认头指针为空
class LinkList:
    def __init__(self):
        self.head = None

    #判断链表是否为空
    def is_empty(self):
        return self.head == None    #若头指针指向为空,则整个链表为空。

    #遍历链表
    def travel(self):
        if self.is_empty(): #遍历之前先判断是否为空链表
            return
        p = self.head   #定义p为指针变量,初始指向头部,与游标具有相同作用(后面的p为同一意义)
        print(p.data)
        while p.next != self.head:
            p = p.next
            print(p.data)
        print('')   #输出链表中的所有值

    #获取链表长度
    def get_length(self):
        p = self.head
        count = 0
        while p != None:    #若p不指向空,即链表不是空链表,则继续计数
            count += 1
            # 若p的指针不指向头结点,则说明还未遍历到最后一个节点,继续遍历;否则终止遍历。
            if p.next != self.head:
                p = p.next
            else:
                break
        return count

    #从前方插入结点
    def add_from_first(self, data):
        NewNode = LinkNode(data)   #插入新结点
        #若原链表为空,则插入的结点即为头结点,其下一个结点即它本身也是头结点(循环链表的特点)
        if self.is_empty():
            self.head = NewNode
            NewNode.next = self.head
        else:
            p = self.head
            while p.next != self.head:
                p = p.next      #将p指向尾结点
            p.next = NewNode   #尾结点指向新插入的结点
            NewNode.next = self.head   #新结点指向原来的头结点
            self.head = NewNode    #新的头结点为新插入的结点

    #从后方插入结点
    def add_from_last(self,data):
        NewNode = LinkNode(data)
        if self.is_empty():
            self.head=NewNode
            NewNode.next=self.head
        else:
            p=self.head
            while p.next != self.head:
                p=p.next
            p.next=NewNode  #尾结点指向新结点
            NewNode.next=self.head  #新结点指向头结点

    #删除操作
    def delete_node(self, id):
        #判断是否为空
        if self.is_empty():
            return '空链表无法删除'
        #判断位置合法
        if id==0 or id > self.get_length():
            return '位置非法'
        #若删除的结点为头结点:
        elif id == 1:
            #若只有一个结点,则只需令其为空即可
            if self.head.next == self.head:
                print(self.head.data)
                self.head = None
            #若不止一个结点:
            else:
                p = self.head
                print(p.data)
                while p.next is not self.head:
                    p = p.next  #将p指向尾结点
                p.next = self.head.next #尾结点指向原头结点的下一个结点
                self.head = self.head.next  #新的头结点为原头结点的下一个结点
        else:
            p = self.head
            for _ in range(id - 2):
                p = p.next  #令p指向删除结点之前一个结点
            print(p.next.data)
            p.next = p.next.next    #删除结点前一个结点指向删除结点后一个结点


#创建JosephusRing指向LinkList类
JosephusRing = LinkList()
PersonNumber=int(input('请输入约瑟夫环的人数'))
id=int(input('请输入从第几个人开始报数'))
skip=int(input('请输入从数到第几个人出局'))
#为创建的链表赋值。由于此时为从前方插入的结点,因此数值需要倒序处理
for i in range(PersonNumber, 0, -1):
    JosephusRing.add_from_first(i)
    
'''若采用尾插法,则代码如下:
for i in range(1,PersonNumber+1):
    JosephusRing.add_from_last(i)
'''

while JosephusRing.get_length()>0:
    if id !=0:
        id= (id+skip-1) % JosephusRing.get_length()
    #若删除尾结点需要特殊处理
    else:
        id=JosephusRing.get_length()
    JosephusRing.delete_node(id)

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