Pyhton笔记02-伪单循环链表实现

还是上次的猴子问题,当时最后一个解法想到的就是通过为链表的方式,不过上次是用了列表做的一个伪链表,这次打算使用类来做一个伪链表。
首先建立一个类作为链表的一个节点,存有值和下一个节点的坐标。

class Node:
    def __init__(self,value,next=None):
        self.value = value
        self.next = next

然后在建立一个伪链表类,里面要有链表的长度和头结点。

class Link:
    def __init__(self,length):#这里需要给定一个初始长度,当然也可以默认为1
        self.length = length
        self.root = self.create_link()#建立链表的方法等会再写

通过初始化确定了表的长度,下面就是向这个链表里面加东西了,由于我这里本来打算是解决猴子出圈问题的(约瑟夫环)所以我默认的给每个节点赋予了代表其编号的初始值。

def create_link(self):
    if self.length <= 0:
        return False
    if self.length ==1:
        root = Node(1)
        return root
    else:
        root = Node(1)
        temp = root#用于存储临时量
        for i in range(2,self.length+1):
        #第n-1的节点的下一个节点为n节点
            temp.next = Node(i)
            #这里面的i是为了给猴子编号用,其实也可以为任意值或者说是[]。
            temp = temp.next#同时将节点n给到临时储存
        temp.next = root
        #for循环走完了之后temp存着的就是最后一个节点,这是让最后一个节点的下一个只想头节点,使这个链表循环。
        self.tail = temp#同时标记处尾节点
        return root

其实有了这个就可以进行猴子问题的探讨了,但是当时我一时兴起有倒腾了一下链表的增删改查。
先说查,我们的每个节点存有两个值,一个是数值,一个是下一个节点的位置,所有第n个节点的位置,我们得去问第n-1个节点,以此类推,最后都要去问第一个节点(除了查找第一个节点),第一个节点的话就直接返回我们在初始化的时候标记的头结点(root),第一个以后的就用for循环来做。直接上代码:

def find_link(self,n):
    if n == 1:
        return self.root
    else:
        temp = self.root#中间过渡
        for i in range(n-1):#为什么是n-1?试试看如果找第二个节点的时候需要循环几次就明白了
            temp = temp.next
        return temp

再说增,这里我们增加的话,我们需要两个值,一个是位置值,一个是该节点的数值。比如链表长是10的话,那么我们输入的位置值应该在什么样的范围?1-10应该没有争议,那么0,11,12行不行?
这里我们假设链表的第一个元素就是第一个而非下标0,那么插入0号位置就显得没有意义了,所以0排除。那么11呢?插入11号位置就是相当于在尾部追加一个元素,这是可以的,那么12呢?链表长就是10,突然插入一个12,也是没有意义的,当然要是较真的话可以说用空值(或者说默认值)占位11,然后在插入12号位。这个应该属于扩充链表长度的范畴了。
所以得把位置值限定在1-11 也就是 1到链表长度+1的范围。
那么要在第n个位置插入值v要如何实现呢?很简单,首先找到n-1的节点,因为他的next指向第n个节点,我们只用改变第n-1个节点的指向,同时让插入的那个元素指向原来的第n个节点就完事了!当然中间得使用temp来过度。对了别忘了给表长+1
对了,那如何找到第n-1个节点呢?参考上面的查。然后,上代码:

def insert_link(self,n,value):
    if n <= 0 or n > self.length+1:#限制长度
        return False
    elif n ==1:#头结点处理,尾节点的next要指向新头节点,同时要标记新头节点
        temp = self.tail
        temp.next = Node(value)
        temp.next.next = self.root
        self.root = temp.next
        self.length += 1
    else:
        self.length += 1
        temp = self.root
        for i in range(n-2):#寻找n-1个节点
            temp = temp.next
        t = temp.next#第n-1个节点储存的next
        temp.next = Node(value)
        if n == self.length:
            self.tail = temp.next#重新标记尾节点
        temp.next.next = t

删也是一样,要先找到n-1个节点,不过不同的是,只用将n-1节点的next指向n+1就完事了,不过要注意头结点和尾节点的重新标记,当然还要记得表长-1:

def del_link(self,n):
    if n <= 0:
        return False
    n = n % self.length
    if n ==0:
        n = self.length
     #上面是n>len导致循环的问题,可以忽略
    if self.length == 1:
        self.root.next = None
       #表长为1在删除的话就是空表了
    elif n == 1:#处理头结点标记
        temp = self.root.next
        self.tail.next = temp
        self.root = self.tail.next
        self.length -= 1
    else:
        if n == self.length:#处理尾节点标记,好吧其实可以用elif。。。。
            self.tail = self.find_link(n-1)
            self.tail.next = self.root
            self.length -= 1
        else:
            temp = self.find_link(n-1)
            temp.next = temp.next.next
            self.length -= 1

改的话就没什么说的了,找到第n个然后改掉:

def change_link(self,n,value):
    self.find_link(n).value = value

增删改查到这里就都写完了,不过有些地方需要改一下就是在搜索范围这块,仅仅是在增的时候有范围的限定,其他地方没有特意去做范围限定,修改之后的整体如下:

class Node:
    def __init__(self,value,next=None):
        self.value = value
        self.next = next
class Link:
    def __init__(self,length):
        self.length = length
        self.root = self.create_link()

    def create_link(self):
        if self.length <= 0:
            return False
        if self.length ==1:
            root = Node(1)
            return root
        else:
            root = Node(1)
            temp = root
            for i in range(2,self.length+1):
                temp.next = Node(i)
                temp = temp.next
            temp.next = root
            self.tail = temp
            return root
    def insert_link(self,n,value):
        if n <= 0 or n > self.length+1:
            return False
        elif n ==1:
            temp = self.tail
            temp.next = Node(value)
            temp.next.next = self.root
            self.root = temp.next
            self.length += 1
        else:
            self.length += 1
            temp = self.root
            for i in range(n-2):
                temp = temp.next
            t = temp.next
            temp.next = Node(value)
            if n == self.length:
                self.tail = temp.next
            temp.next.next = t
    def del_link(self,n):
        if n <= 0 or n >self.length:
            return False
        if self.length == 1:
            self.root.next = None
        elif n == 1:
            temp = self.root.next
            self.tail.next = temp
            self.root = self.tail.next
            self.length -= 1
        else:
            if n == self.length:
                self.tail = self.find_link(n-1)
                self.tail.next = self.root
                self.length -= 1
            else:
                temp = self.find_link(n-1)
                temp.next = temp.next.next
                self.length -= 1
    def change_link(self,n,value):
        if n <= 0 or n >self.length:
            return False
        self.find_link(n).value = value
    def find_link(self,n):
        if n <= 0 or n >self.length:
            return False
        if n == 1:
            return self.root
        else:
            temp = self.root
            for i in range(n-1):
                temp = temp.next
            return temp
    def show_link(self):#增加了显示全部的方法
        temp = self.root
        while True:
            print(temp.value,end=' ')
            temp = temp.next
            if temp == None or temp == self.root:#碰到空或者碰到尾节点(下一个指向头节点的节点)
                print()
                break

折腾了半天不能忘记了初衷,解决猴子问题!

def king(n,m,k):
    monkey = Link(n)
    temp = monkey.root
    while True:
        for i in range(m-2):
            temp = temp.next
        temp.next = temp.next.next
        #数到第m-1个 踢出m个
        temp = temp.next
        monkey.length -= 1#表长记得-1
        if monkey.length == k:
            for i in range(k):#循环打印剩余的猴子
                print(temp.value)
                temp = temp.next
            break

猜你喜欢

转载自blog.csdn.net/q275343119/article/details/82320709