简体   繁体   中英

Remove the last node from a circular linked list in python

I am trying to pop elements from the end of a circular linked list in python. All the elements are getting popped successfully, but error arises when only one node is left. When the last remaining node is popped an error occurs. Is there any problem with the show function?

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

class CircularLinkedList(object):
    def __init__(self, tail = None):
        self.tail = tail
    def append(self, value):
        new_node = Node(value)
        if self.tail ==None:
            self.tail = new_node
            self.tail.next = new_node
        if self.tail!=None:
            new_node.next= self.tail.next
            self.tail.next=new_node
            self.tail= new_node
   
    #pop function
    def pop(self):
        if self.tail==None:
            print("Sorry no elements .")
        else:
            if self.tail.next==self.tail:          
                self.tail=None
                return self.tail

            else:
                temp=self.tail.next
                while temp.next!=self.tail:
                    temp=temp.next
                temp.next=self.tail.next
                removed = self.tail
                self.tail=temp
                print("Popped")
                return removed
        #display function
    def show(self):
        current = self.tail
        while current.next:
            current = current.next
            print(current.value)
            if current == self.tail:
                break


circular = CircularLinkedList()
circular.append(5)
circular.append(9)
circular.append(96)
print("Before deleting:")
circular.show()
circular.pop()
circular.pop()
circular.pop()
circular.show()   

Image of the output

When you pop the last element you assign None to self.tail , so in show() in

while current.next:

you are trying to call next from None . Add a check

while current and current.next:

I fixed it so your image shows. The problem is not the popping of the last value. You're doing that correctly. The problem is that your show function cannot handle an empty list. You need to check for that.

You need to make a little change to you pop function to understand how many elements got popped.

Like this

def pop(self):
        if self.tail==None:
            print("Sorry no elements .")
        else:
            if self.tail.next==self.tail:          
                self.tail=None
                print("popped")  #HERE
                return self.tail

            else:
                temp=self.tail.next
                while temp.next!=self.tail:
                    temp=temp.next
                temp.next=self.tail.next
                removed = self.tail
                self.tail=temp
                print("Popped")
                return removed

This will make things clear for you. And as others said, the reason for your error is in your show method.

You're making self.tail=None for the last element in pop() . And you're trying to access .next for None .

Here:

def show(self):
        current = self.tail
        while current.next:

Add an if like this to avoid error

def show(self):
        current = self.tail
        if current.next == None:
           print("circular linkedlist is empty")
           return None
        while current.next:
            current = current.next
            print(current.value)
            if current == self.tail:
                break

There are the following issues in your code:

  • In the pop method None is returned when the only remaining node is removed. But it should return the removed node. This happens here:

     self.tail=None return self.tail # <-- this will always be None!

    Change the pop function to this:

     def pop(self): if not self.tail: print("Sorry no elements.") else: removed = self.tail # also when the only remaining node! if self.tail.next == self.tail: self.tail = None else: temp = self.tail.next while temp.next != self.tail: temp = temp.next temp.next = self.tail.next self.tail = temp print("Popped") return removed
  • The show method assumes that the list is not empty. For an empty list it will generate an error on this statement:

     while current.next:

    So deal with the empty list case separately. Also, it is strange to have this while condition, as there is a break inside the loop, that depends on a more useful condition: make that the loop condition. You could write that method as follows:

     def show(self): if not self.tail: print("(empty)") return current = self.tail.next while current != self.tail: print(current.value, end=" ") current = current.next print(self.tail.value)

Not an error, but the append method is a bit weird in how it inserts the first node: it will execute both the if blocks. It ends up working correctly, but I find that counter-intuitive. It seems better to write this as an if...else structure, so that exactly one block of code gets executed, not two:

def append(self, value):
    new_node = Node(value)
    if self.tail:
        new_node.next = new_node
    else:
        new_node.next = self.tail.next
        self.tail.next = new_node
    self.tail = new_node

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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