简体   繁体   English

如何创建递归 function 以从 python 中给定键的链表中删除节点?

[英]How to create a recursive function to delete node from linked list with given key in python?

I tried program to delete node from linked list recursively.我尝试程序递归地从链表中删除节点。 My program is given below我的程序如下

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

class linkedList:
    def __init__(self):
        self.head=None

    def printList(self):
        cur = self.head
        while(cur != None):
            print(cur.data,end="->")
            cur=cur.next
        print("null")

    def push(self,dat):
        newNode = node(dat)

        temp = self.head
        self.head = newNode

        newNode.next = temp

    @staticmethod
    def dnr(head, key):
        if head is not None:
            if head.data == key:
                head=head.next
                return head
        if head is not None:
            head.next = linkedList.dnr(head.next, key)
            return head
        return head


    

if __name__ == '__main__':
    ll=linkedList()

    ll.push(3)
    ll.push(6)
    ll.push(9)
    ll.push(12)
    ll.push(15)

    ll.printList()
    print("*******")

    # ll.head = linkedList.dnr(ll.head,2)
    linkedList.dnr(ll.head,9)
    ll.printList()

The problem with this is that this does not work for first element.To make it work for first element I have to call the function like this ll.head = linkedList.dnr(ll.head,2)问题是这对第一个元素不起作用。要使其对第一个元素起作用,我必须像这样调用 function ll.head = linkedList.dnr(ll.head,2)

second thing is that I wanted my function to call this way ll.dnr(2)第二件事是我希望我的 function 以这种方式调用ll.dnr(2)

please tell me how to create a recursive function to delete node in linked list in python请告诉我如何创建递归 function 以删除 python 链表中的节点

I rewrote your code:我重写了你的代码:

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

class linkedList:
    def __init__(self):
        self.__head=None

    def printList(self):
        cur = self.__head
        while(cur != None):
            print(cur.data,end="->")
            cur=cur.next
        print("null")

    def push(self,dat):
        newNode = node(dat)

        temp = self.__head
        self.__head = newNode

        newNode.next = temp
    
    @staticmethod
    def __dnr(head, key):
        if head is None: 
            return head
        if head.data == key:
            head = head.next
            return head
        head.next = linkedList.__dnr(head.next, key)
        return head
    
    @staticmethod
    def dnr(listObj, key):
        if listObj is None or listObj.__head is None: 
            return listObj
        if listObj.__head.data == key:
            listObj.__head = listObj.__head
        listObj.__head = linkedList.__dnr(listObj.__head, key)

    def deleteKey(self, key):
        linkedList.dnr(self, key)

if __name__ == '__main__':
    ll=linkedList()

    ll.push(3)
    ll.push(6)
    ll.push(9)
    ll.push(12)
    ll.push(15)

    ll.printList()
    print("*******")

    linkedList.dnr(ll, 9)
    ll.deleteKey(12)
    ll.printList()

I made head variable inside linkedList class private, it's not smart to give access outer world to class core components.我在linkedList class 中将head变量设为私有,将外部世界的访问权限授予 class 核心组件并不明智。 And class core components should never leak to the outer world because if it's that not used properly that can cause errors.并且 class 核心组件绝不能泄漏到外部世界,因为如果使用不当,可能会导致错误。 So I rewrote your dnr function and now it's more clear and it doesn't return head object which is core component of linkedList class. Now dnr function just check if passed listObj is valid and check if head is that node that should be deleted.所以我重写了你的dnr function,现在它更清楚了,它不会返回head object,它是linkedList class 的核心组件。现在dnr function 只检查传递的listObj是否有效,并检查head是否是应该删除的节点。 After that it calls private static __dnr function to delete node with given key .之后,它调用 private static __dnr function 来删除具有给定key的节点。 Function deleteKey can be called like this ll.deleteKey(12) , that is what you wanted. Function deleteKey可以这样调用ll.deleteKey(12) ,这就是你想要的。

Giving core component accessible through outer world is like giving bank customer access to a bank vault.让核心组件可以通过外部世界访问就像让银行客户访问银行金库一样。 Not everybody will try to steal money from it, but there will be someone who will try.不是每个人都会尝试从中偷钱,但总会有人尝试。

If you don't understand private variables follow this link .如果您不了解私有变量,请点击此链接

I wanted my function to call this way ll.dnr(2)我想让我的 function 以这种方式调用ll.dnr(2)

Then you need to define an instance method.然后你需要定义一个实例方法。 Your static function can serve a purpose, but as you noted, you really need to assign its return value back to your list's head attribute to be sure it also works when the original head node is removed.您的static function 可以发挥作用,但正如您所指出的,您确实需要将其返回值分配回列表的head属性,以确保它在删除原始头节点时也能正常工作。 With your static method you cannot avoid this overhead, since that method has no knowledge about your linkedList instance.使用您的 static 方法您无法避免这种开销,因为该方法不知道您的 linkedList 实例。

You can achieve what you want simply by adding an instance method, that will rely on the existing static method and will deal with this assignment back to the instance's head attribute.您只需添加一个实例方法即可实现您想要的效果,该方法将依赖于现有的 static 方法并将处理此赋值返回给实例的head属性。

Add this to your linkedList class:将此添加到您的链接列表linkedList

    def remove(self, key):
        self.head = linkedList.dnr(self.head, key)

Now in your main program you can do:现在在你的主程序中你可以这样做:

    ll.remove(15)

Side note: you don't need the second if head is not None: check in your static method, as this condition will always be true when the execution reaches that point in your code.旁注: if head is not None:检查 static 方法,因为当执行到代码中的那个点时,此条件将始终为真。 Just do the assignment to head.next unconditionally.只需无条件地对head.next进行赋值即可。

Addendum附录

If you want dnr itself to become an instance method (without addition of a remove method), then you need to temporarily cut off the head node from the list (even if you want to keep it), recur, and then conditionally add that cut-off node again (if it's key is not the one to delete).如果想让dnr本身变成一个实例方法(不加remove方法),那么就需要把头结点从链表中临时切掉(即使想保留),recur,然后有条件的把那个切掉的加进去-再次关闭节点(如果它的键不是要删除的那个)。

It would look like this:它看起来像这样:

    def dnr(self, key):
        head = self.head
        if head:
            self.head = head.next # Skip
            if head.data != key: # Need to restore it
                self.dnr(key) # But first look further...
                head.next = self.head # Prefix the removed node
                self.head = head  # ...and make it the head again

You would call like:你会这样打电话:

    ll.dnr(15)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM