LinkedList - NameError: name 'target' is not defined - python

I am learning about LinkedList. I ran this once. But when I am trying to run this code once again It didn't work out. I wonder why. The error shows when I'm trying to call the method "remove"
Firstly, a class of linkedlist has been created. And then we add new method to this class. The method "addFirst" is used to insert element at the beginning of the linkedlist. On the other hand, the method "addLast" is used to insert element at the end of the linkedlist. "addAfter" is used to insert element after a target node. Similar to the method "addBefore" While method "remove" is used to remove a node in the linkedlist.
class LinkedList:
def __init__(self):
self.head = None
def __repr__(self):
node = self.head
nodes = []
while node is not None:
nodes.append(node.data)
node = node.next
nodes.append("None")
return " -> ".join(nodes)
def __iter__(self):
node = self.head
while node is not None:
yield node
node = node.next
def add_first(self, node):
node.next = self.head
self.head = node
def add_last(self, node):
if self.head is None:
self.head = node
return
for current_node in self:
pass
current_node.next = node
def add_after(self, target_node_data, new_node):
if self.head is None:
raise Exception("List is empty")
for node in self:
if node.data == target_node_data:
new_node.next = node.next
node.next = new_node
return
raise Exception("Target not found")
def add_before(self, target_node_data, new_node):
if self.head is None:
raise Exception("List is empty")
if self.head.data == target_node_data:
return self.add_first(new_node)
prev_node = self.head
for node in self:
if node.data == target_node_data:
prev_node.next = new_node
new_node.next = node
return
prev_node = node
raise Exception("Target Node not found")
def remove_node(self, target_node_data):
if self.head is None:
raise Exception("List is empty")
if self.head.data == target_node_data:
self.head = self.head.next
return
previous_node = self.head
for node in self:
if node.data == target.node.data:
previous_node.next = node.next
node.next = None
return
previous_node = node
raise Exception("Target Node not found")
class Node:
def __init__(self, data):
self.data = data
self.next = None
def __repr__(self):
return self.data
llist = LinkedList()
first_node = Node("a")
llist.head = first_node
second_node = Node("b")
third_node = Node("c")
first_node.next = second_node
second_node.next = third_node
for node in llist:
print(node)
llist.add_first(Node("b2"))
llist
llist.add_last(Node("b"))
llist
llist.add_after("a", Node("b"))
llist
llist.remove_node("a")

Should be target_node_data not target.node.data:
class LinkedList:
def __init__(self):
self.head = None
def __repr__(self):
node = self.head
nodes = []
while node is not None:
nodes.append(node.data)
node = node.next
nodes.append("None")
return " -> ".join(nodes)
def __iter__(self):
node = self.head
while node is not None:
yield node
node = node.next
def add_first(self, node):
node.next = self.head
self.head = node
def add_last(self, node):
if self.head is None:
self.head = node
return
for current_node in self:
pass
current_node.next = node
def add_after(self, target_node_data, new_node):
if self.head is None:
raise Exception("List is empty")
for node in self:
if node.data == target_node_data:
new_node.next = node.next
node.next = new_node
return
raise Exception("Target not found")
def add_before(self, target_node_data, new_node):
if self.head is None:
raise Exception("List is empty")
if self.head.data == target_node_data:
return self.add_first(new_node)
prev_node = self.head
for node in self:
if node.data == target_node_data:
prev_node.next = new_node
new_node.next = node
return
prev_node = node
raise Exception("Target Node not found")
def remove_node(self, target_node_data):
if self.head is None:
raise Exception("List is empty")
if self.head.data == target_node_data:
self.head = self.head.next
return
previous_node = self.head
for node in self:
if node.data == target_node_data:
previous_node.next = node.next
node.next = None
return
previous_node = node
raise Exception("Target Node not found")
class Node:
def __init__(self, data):
self.data = data
self.next = None
def __repr__(self):
return self.data
llist = LinkedList()
first_node = Node("a")
llist.head = first_node
second_node = Node("b")
third_node = Node("c")
first_node.next = second_node
second_node.next = third_node
for node in llist:
print(node)
llist.add_first(Node("b2"))
llist
llist.add_last(Node("b"))
llist
llist.add_after("a", Node("b"))
llist
llist.remove_node("a")

Related

LinkedList implementation in Python not showing beyond the head node

My attempts at creating a linked list from scratch in Python are not working, and I'm not sure what I am missing. I tried to create separate classes for nodes and linked lists, but when I am trying to see beyond the head node, I hit a road block.
Appreciate any pointers (no pun intended). Also, what is a better approach: have a separate class for the nodes, or make them an attribute of the linked list class itself?
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class LinkedList:
def __init__(self):
self.head = None
# adding/inserting to the tail
def add(self, val):
node_to_add = ListNode()
if self.head == None:
self.head = node_to_add
node_to_add.val = val
else:
self.next = node_to_add
node_to_add.val = val
# printing the linked list as a list
def print(self):
list_to_print = []
if not self.head:
return None
node_to_read = self.head
while self.head:
list_to_print.append(node_to_read.val)
if node_to_read.next:
self.head = node_to_read.next
else:
return list_to_print
When I run this code, I only can print the head node. When I add nodes/values after the first entry, the print() only returns the head.
test1 = LinkedList()
test1.add(1)
test1.add(4)
test1.add(7)
test1.print()
the output is
[1]
In order to append items to the last Node you need to keep track of the last node.
You also should not override your head pointer in the print function.
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class LinkedList:
def __init__(self):
self.head = None
self.tail = None
# adding/inserting to the tail
def add(self, val):
node_to_add = ListNode()
node_to_add.val = val
if self.tail == None:
self.head = node_to_add
self.tail = node_to_add
else:
self.tail.next = node_to_add
self.tail = node_to_add
# printing the linked list as a list
def print(self):
list_to_print = []
if not self.head:
return None
current_node = self.head
while current_node:
list_to_print.append(current_node.val)
if current_node.next:
current_node = current_node.next
else:
return list_to_print
You can simplify this significantly by giving the node responsibility for adding children. This makes the linked list object basically a wrapper that manages the head and iterations over the list:
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def add(self, node):
if self.next is None:
self.next = node
else:
self.next.add(node)
class LinkedList:
def __init__(self):
self.head = None
def add(self, val):
node = ListNode(val)
if self.head == None:
self.head = node
else:
self.head.add(node)
# printing the linked list as a list
def print(self):
list_to_print = []
node_to_read = self.head
while node_to_read:
list_to_print.append(node_to_read.val)
node_to_read = node_to_read.next
print(list_to_print)
test1 = LinkedList()
test1.add(1)
test1.add(4)
test1.add(7)
test1.print()
# [1, 4, 7]

My compiler keeps displaying this error "TypeError: add_node() missing 1 required positional argument: 'data'"

I am trying to create a Python Method that adds a new Node to the linked list, given below is the code I have written but, when I execute it, the compiler keeps asking for some "positional argument" that I am missing apparently
class Node:
def __init__(self, data, next_node=None):
self.data = data
self.next = next_node
class LinkedList:
def __init__(self):
self.head = Node
self.head.next = None
def add_node(self,data):
new_node = Node(data)
# checks if the linked list is empty or not
if self.head is None:
self.head = new_node
# seeker traverses through the list to find the final node of the list
seeker = self.head
# traversing through the list
while seeker.next is not None:
seeker = seeker.next
# adding new node to the list
seeker.next = new_node
# setting the pointer to None/Null again
new_node.next = None
if __name__ == '__main__':
ListA = LinkedList
ListA.add_node(5)
Your code should be like this:
class Node:
def __init__(self, data=None, next_node=None):
self.data = data
self.next = next_node
class LinkedList:
def __init__(self):
self.head = Node()
self.head.next = None
def add_node(self, data):
new_node = Node(data)
# checks if the linked list is empty or not
if self.head is None:
self.head = new_node
# seeker traverses through the list to find the final node of the list
seeker = self.head
# traversing through the list
while seeker.next is not None:
seeker = seeker.next
# adding new node to the list
seeker.next = new_node
# setting the pointer to None/Null again
new_node.next = None
if __name__ == '__main__':
ListA = LinkedList()
ListA.add_node(5)

Why do we need to put self as the argument while calling another class function

I understand that while defining functions we have to use self as the first argument but in my particular coding example for insert_node method I got an error while calling insert_node(node,new_node) saying 3 arguments expected when I did not use self as the first argument in insert_node
class Node:
def __init__(self,value=None):
self.value = value
self.left = None
self.right = None
class BST:
def __init__(self,value=None):
self.root = Node(value)
def insert(self,value):
if self.root == None:
self.root = Node(value)
return
curr = self.root
new_node = Node(value)
def insert_node(self,node,new_node):
if node.value == new_node.value:
return
if node.value > new_node.value:
if node.left is None:
node.left = new_node
return
else:
insert_node(self,node.left,new_node)
else:
if node.right is None:
node.right = new_node
return
else:
insert_node(self,node.right,new_node)
insert_node(self,curr,new_node)
insert_node() is not a method, it is a function nested inside insert(). You don't need to use self in this function, at all, because it makes no use of that argument, and even if it did, it could access the self reference from the parent insert() method as a closure.
Removing the self argument altogether works:
class BST:
def __init__(self,value=None):
self.root = Node(value)
def insert(self,value):
if self.root == None:
self.root = Node(value)
return
curr = self.root
new_node = Node(value)
def insert_node(node, new_node):
if node.value == new_node.value:
return
if node.value > new_node.value:
if node.left is None:
node.left = new_node
return
else:
insert_node(node.left, new_node)
else:
if node.right is None:
node.right = new_node
return
else:
insert_node(node.right, new_node)
insert_node(curr, new_node)
You can move that function out of the insert() method too, it doesn't need to be nested there:
def insert_node(node, new_node):
if node.value == new_node.value:
return
if node.value > new_node.value:
if node.left is None:
node.left = new_node
return
else:
insert_node(node.left, new_node)
else:
if node.right is None:
node.right = new_node
return
else:
insert_node(node.right, new_node)
class BST:
def __init__(self,value=None):
self.root = Node(value)
def insert(self,value):
if self.root == None:
self.root = Node(value)
return
curr = self.root
new_node = Node(value)
insert_node(curr, new_node)
However, this really should be a method on the Node class:
class Node:
def __init__(self, value=None):
self.value = value
self.left = None
self.right = None
def insert_node(self, new_node):
if self.value == new_node.value:
return
if self.value > new_node.value:
if self.left is None:
self.left = new_node
return
else:
self.left.insert_node(new_node)
else:
if self.right is None:
self.right = new_node
return
else:
self.right.insert_node(new_node)
class BST:
def __init__(self,value=None):
self.root = Node(value)
def insert(self,value):
if self.root == None:
self.root = Node(value)
return
curr = self.root
new_node = Node(value)
curr.insert_node(new_node)
Because you access insert_node() on Node instances (via curr.insert_node(...), self.left.insert_node(...) and self.right.insert_node(...), it is bound to that instance for you by Python, and passed into the method as self.

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.

LinkedList code in python

__author__ = 'jarvis'
class Node:
def __init__(self, num):
self.next = None
self.data = num
class LList:
def __init__(self, h=None):
self.head = None
def insert_node(self, num):
node = Node(num)
if self.head is None:
self.head = node
else:
node.next = self.head
self.head = node
def print_list(self):
node = self.head
while not (node is None):
print node.data
node = node.next
lis = LList()
lis.insert_node(10)
lis.insert_node(20)
lis.insert_node(30)
lis.print_list()
I am very new to Python. I am trying to create a LinkedList. No error is shown but nothing is getting displayed. When I am trying to debug. The program is exiting without anything happening. Not able to understand what the problem is.
You shouldn't be setting node.next = self.head. You should be maintaining a pointer to both the head and tail. I've modified your code below.
class Node:
def __init__(self, num):
self.next = None
self.data = num
class LList:
def __init__(self, h=None):
self.head = None
self.tail = None
def insert_node(self, num):
node = Node(num)
if self.head is None:
self.head = node
self.tail = self.head
else:
self.tail.next= node
self.tail = node
def print_list(self):
node = self.head
while not (node is None):
print node.data
node = node.next

Categories