Home > Mobile >  How to create a recursive function to delete node from linked list with given key in python?
How to create a recursive function to delete node from linked list with given key in python?

Time:05-15

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)

second thing is that I wanted my function to call this way ll.dnr(2)

please tell me how to create a recursive function to delete node in linked list in python

CodePudding user response:

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. And class core components should never leak to the outer world because if it's that not used properly that can cause errors. 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. After that it calls private static __dnr function to delete node with given key. Function deleteKey can be called like this ll.deleteKey(12), that is what you wanted.

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.

CodePudding user response:

I wanted my function to call this way 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. With your static method you cannot avoid this overhead, since that method has no knowledge about your linkedList instance.

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.

Add this to your linkedList class:

    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. Just do the assignment to head.next unconditionally.

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

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)
  • Related