reversing a linkedlist using 3 pointers - python

reversing a linkedlist using 3 pointer?
cant understand what is the problem?
pls suggest any other iterative solution too..
reversing a linkedlist using 3 pointer?
cant understand what is the problem?
pls suggest any other iterative solution too..
outcome should be 87654321(reverse of a linkedlist)
but currently the output is 1
i think there is problem in reverse function pointers
reversing a linkedlist
class Node:
def __init__(self,data):
self.data=data
self.next=None
class LinkedList:
def __init__(self):
self.head=None
def push(self,data):
new_node=Node(data)
new_node.next=self.head
self.head=new_node
def printlist(self):
temp=self.head
print()
while temp:
print(temp.data,end=' ')
temp=temp.next
def append(self, new_data):
new_node = Node(new_data)
if self.head is None:
self.head = new_node
return
last = self.head
while (last.next):
last = last.next
last.next = new_node
def reverse(self):
prev=None
current=self.head
nnext=current.next
while nnext:
current.next=prev
prev = current
current = nnext
nnext=nnext.next
current.next=prev
if __name__=='__main__':
llist=LinkedList()
llist.append(1)
llist.append(2)
llist.append(3)
llist.append(4)
llist.append(5)
llist.append(6)
llist.append(7)
llist.append(8)
llist.printlist()
llist.reverse()
llist.printlist()

Well, your code generally works fine. What you miss is assigning self.head in the end of your reverse method. Just add this line self.head = current to the end of reverse and it works fine.

Related

Python Linkledlist addNode() not correct

I'm writing a simple linked list implementation and am struggling to understand why my code doesn't work. I have a ListNode class and a LinkedList node which contains the head and tail nodes of the list. The addNode() function simply creates a new ListNode, change the self.tail.next = newNode, then set the tail to be the newNode.
When I try to run the following code, I would get the error "AttributeError: 'int' object has no attribute 'next'".
l1 = LinkedList(1)
l1.addNode(2)
l1.addNode(4)
Thank you for the help!
Here is my code
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class LinkedList:
def __init__(self, head=ListNode()):
self.head = head
self.tail = head
def addNode(self, val=0):
newNode = ListNode(val)
self.tail.next = newNode
self.tail = newNode
On the first line of your code, you're passing the value 1 to LinkedList, which is an integer, not an instance of ListNode.
So, you should write l1 = LinkedList(ListNode(1)).

'int' object has no attribute 'next'

So i've been trying to solve a problem in leetcode that is to design a linked list. Here's what i tried:
class Node:
def __init__(self,next=None,val=None):
self.next = next
self.val = val
class Linked_list(object):
def __init__(self):
self.head = None
self.length = 0
def insertAtEnd(self, val):
new_node = Node(val)
if self.head is None:
self.head = new_node
else:
itr = self.head
while itr.next: #Error
itr = itr.next
itr.next = new_node
self.length += 1
So in the insertAtEnd method when i try to iterate over the list it shows the error that self.head is an an int object. I'm struggling to find an answer here. So please help me out. Thank you!
Your code is fine but I found one bug there
new_node = Node(val)
But constructor looks:
def __init__(self,next=None,val=None):
self.next = next
self.val = val
So you pass your val to next parameter and self.head.next points to val which is int. Probably you ment
new_node = Node(val=val)
Or alternatively, change order of next and val in Node constructor.

how is the object using a variable which is not inside the class or defined anywhere

In this code the object of class Node is using a variable next which is not defined anywhere and the code is still working HOW?How is the object using a variable which is not defined in its class
class Node:
def __init__(self, data):
self.data = data
class LinkedList:
# Function to initialize head
def __init__(self):
self.head = None
# Function to reverse the linked list
def reverse(self):
prev = None
current = self.head
while(current is not None):
next = current.next
current.next = prev
prev = current
current = next
self.head = prev
# Function to insert a new node at the beginning
def push(self, new_data):
new_node = Node(new_data)
new_node.next = self.head
self.head = new_node
# Utility function to print the linked LinkedList
def printList(self):
temp = self.head
while(temp):
print(temp.data)
temp = temp.next
llist = LinkedList()
llist.push(20)
llist.push(4)
llist.push(15)
llist.push(85)
print( "Given Linked List")
llist.printList()
llist.reverse()
print ("\nReversed Linked List")
llist.printList()
While in most strongly typed languages this is not possible, Python allows instance attributes to be defined even after the instance has been created and the constructor has run. As long as code does not reference an attribute before it has been defined, there is no issue. See also: Can I declare Python class fields outside the constructor method?
In this particular case the following code would produce an error:
node = Node(42)
if node.next: # Attribute error
print("42 is not the last node")
else:
print("42 is the last node")
However, the only place where new node instances are created is in the push method of the LinkedList class:
def push(self, new_data):
new_node = Node(new_data)
new_node.next = self.head
self.head = new_node
As you can see, the next attribute is defined immediately after the node is constructed. So in practice, every node in a linked list will have a next attribute.
Best Practice?
It is open for debate whether this coding practice is advisable. For instance, Pylint has a rule defining-attr-methods which by default will raise a warning when attributes are defined outside of __init__, __new__, setUp, or __post_init__.
Alternative
In this scenario I would certainly prefer to define the next attribute in the constructor, and give the constructor an extra, optional parameter with which next can be initialised:
class Node:
def __init__(self, data, nxt=None):
self.data = data
self.next = nxt
With this change, the push method of the LinkedList class can be reduce to just:
class LinkedList:
# ...
def push(self, new_data):
self.head = Node(new_data, self.head)
That looks a lot more elegant.
Unrelated, but I would also let the constructor of LinkedList accept any number of values to initialise the list with:
class LinkedList:
def __init__(self, *values):
self.head = None
for value in reversed(values):
self.push(value)
Now the main code could create a list with 4 values in one go:
llist = LinkedList(85, 15, 4, 20)

Is there a way calling a variable without declaring it

I'm learning a course of Data Structures and Algorithm. There's a quiz that request me to write some codes that describe Linked List type:
class LinkedList(object):
def __init__(self, head):
self.head = head
def append(self, new_element):
current = self.head
if self.head:
while current.next:
current = current.next
current.next = new_element
else:
self.head = new_element
The code above is the example that the course made for me. But there's something I don't understand is in the "while current.next" loop, it's clearly that the "current.next" variable hasn't been declared. I have researched about the "next" thing but it's just about the next () method.
Here's the course if you interest: https://classroom.udacity.com/courses/ud513/lessons/7117335401/concepts/78875247320923
The .next attribute has to be provided by the thing you pass in when constructing the linked list and append objects to it.
Here is a very basic example of how this could work
class LinkedList(object):
def __init__(self, head):
self.head = head
def append(self, new_element):
current = self.head
if self.head:
while current.next:
current = current.next
current.next = new_element
else:
self.head = new_element
#added for demonstration
def output_values(self):
current = self.head
while current:
print(current.value)
current = current.next
class LinkedObject:
next = None
value = None
def __init__(self, val=None, nextObject=None):
if nextObject:
self.next = nextObject
if val:
self.value = val
ll = LinkedList(LinkedObject(5))
ll.append(LinkedObject(24))
ll.append(LinkedObject(332))
ll.output_values()

why is "append" method not working correctly?

The "append" method is not working correctly.
It's only going inside the 'if" statement of the "append' method and not entering into the while loop.
class Node:
def __init__(self,data=None):
self.data=data
self.next=None
class Linkedlist:
def __init__(self):
self.head=Node()
def append(self,data):
new_node=Node(data)
if self.head.data is None:
self.head=new_node
cur_node=self.head
while cur_node.next is not None:
cur_node=cur_node.next
cur_node=new_node
def insert_after_node(self,prev_node,data):
new_node=Node(data)
if prev_node is None:
print("node that you have entered does not exist")
new_node.next=prev_node.next
prev_node.next=new_node
def display(self):
current=self.head
while current.next is not None:
print(current.data)
current=current.next
List=Linkedlist()
List.append("A")
List.append("B")
List.append("C")
List.insert_after_node(List.head,"g")
List.display()
Expected output: AgBC
Actual Output: A
Your .append() method simply sets a local variable to cur_node to point to new_node. This doesn't change the linked list at all; the last node in the link that was previously assigned to that local variable is not changed.
You instead want to assign to the .next attribute of the last node:
cur_node.next = new_node
The while loop in the method is working fine otherwise.
You also should not use new_node twice, when the list is empty. Exit when you don't yet have a head node with data:
if self.head.data is None:
self.head=new_node
return
Personally, I'd set self.head = None instead of self.head = Node(), then use if self.head is None:.
Next, your display function forgets to print the last element. Rather than test for current.next, check if current is None; this is where setting self.head to None for an empty list would work a lot better:
def display(self):
current = self.head
while current is not None
print(current.data)
current = current.next
I had the exact same question as you, but my implementation was different and it seems to work just fine.
First I created a node class with all its different methods:
class Node:
def __init__(self, init_data):
self.data = init_data
self.next = None
def get_data(self):
return self.data
def get_next(self):
return self.next
def set_data(self, new_data):
self.data = new_data
def set_next(self, new_next):
self.next= new_next
The I created my UnorderedList class with its methods too, including append. insert, index and pop I am still working on...
class UnorderedList:
"""
An unordered list class built from a collection of nodes.
"""
def __init__(self):
self.head = None
def is_empty(self):
return self.head == None
def add(self, item):
temp = Node(item)
temp.set_next(self.head)
self.head = temp
def size(self):
current = self.head
count = 0
while current != None:
count += 1
current = current.get_next()
return count
def search(self, item):
current = self.head
found = False
while current != None and not found:
if current.get_data() == item:
found = True
else:
current = current.get_next()
return found
def remove(self, item):
current = self.head
previous = None
found = False
while not found:
if current.get_data() == item:
found = True
else:
previous = current
current = current.get_next()
if previous == None:
self.head = current.get_next()
else:
previous.set_next(current.get_next())
def print_list(self):
current = self.head
while current != None:
print(current.data)
current = current.get_next()
def append(self, item):
new_node = Node(item)
if self.head == None:
self.head = new_node
return
current = self.head
found_last = False
while not found_last:
if current.get_next() == None:
found_last = True
current.set_next(new_node)
else:
current = current.get_next()
def insert(self, item, pos):
pass
def index(self, item):
pass
def pop(self):
pass
I realize my version of append is more verbose, but I was using the traversal method I previously used as part of my size method to make it work, and it seems to work just fine.
I found it easier to create a Node class with its methods separately as it made it easier to visualize how to set the next node and get data from the current one. Hope this helps!
FYI the node class and a lot of the UnorderedList is straight out of Problem Solving with Algorithms and Data Structures in Python by David Ranum and Brad Miller, so I know they work fine!
class Node:
def __init__(self,data=None):
self.data=data
self.next=None
class LinkedList():
def __init__(self):
self.head=Node()
def append(self,data):
new_node=Node(data)
if self.head.data is None:
self.head=new_node
else:
cur_node=self.head
while cur_node.next is not None:
cur_node=cur_node.next
cur_node.next=new_node
def insert_after_node(self,prev_node,data):
new_node=Node(data)
if prev_node is None:
print("node that you have entered does not exist")
new_node.next=prev_node.next
prev_node.next=new_node
def display(self):
current=self.head
while current.next is not None:
print(current.data)
current=current.next
print(current.data)
List=LinkedList()
List.append("A")
List.append("B")
List.append("C")
List.insert_after_node(List.head,"g")
Fixed some bugs for you:
The class name LinkedList mismatch problem
In append, if self.head.data is None, it should set self.head and then return.
In the else part of append, let the last node point to the new node by cur_node.next=new_node
In display, the last node should also be printed.

Categories