My question is, will the object Node(3) still be in RAM memory once we reach the end of remove() function ? If no, when is it deleted from RAM memory ?
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def add(self, data):
if self.head is None:
self.head = Node(data)
else:
curr_node = self.head
while (curr_node.next):
curr_node = curr_node.next
curr_node.next = Node(data)
def remove(self, data):
if self.head is not None:
if self.head.data == data:
self.head = self.head.next
else:
curr_node = self.head
while curr_node.next is not None:
if curr_node.next.data == data:
curr_node.next = curr_node.next.next
break
curr_node = curr_node.next
l = LinkedList()
l.add(2)
l.add(3)
l.add(4)
l.remove(3)
# program going on ...
Related
i am using a while to add a node to my linked list after a value provided.
but it is not working accordingly.
I have done print command inside while loop it's showing that it works fine as I want, but when I am printing list it's not.
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LInkedList:
def __init__(self):
self.head = None
def print_list(self):
cur_node = self.head
while cur_node:
print(cur_node.data)
cur_node = cur_node.next
def apppend(self, data):
new_node = Node(data)
if self.head is None:
new_node = self.head
return
last_node = self.head
while last_node.next is not None:
last_node = last_node.next
last_node.next = new_node
def prepend(self, data):
new_node = Node(data)
new_node.next = self.head
self.head = new_node
def add_after_node(self, after, data):
new_node = Node(data)
this_node = self.head
while this_node:
if this_node.data == after:
new_node.next = this_node.next
this_node.next = new_node
# print(this_node.data) this shows that is updating properly
this_node = this_node.next
new_list = LInkedList()
new_list.prepend(10)
new_list.prepend(20)
new_list.prepend(30)
new_list.prepend(20)
new_list.add_after_node(20, 50)
new_list.print_list()
I want that 50 should be added after each 20 in the list.
for example:
input :- 20 30 20 10
output :- 20 50 30 20 50 10
right now it is printing 20 50 10 with print_list function I don't know why?
This is my code ignore if any of the spacing is wrong the code works perfectly fine in python.
class Node:
def __init__(self, value):
self.value = value
self.next = None
def __str__(self):
return "Node({})".format(self.value)
def getNext(self):
return self.next
def getValue(self):
return self.value
def setNext(self, new_next):
self.next = new_next
def setValue(self, new_value):
self.value = new_value
__repr__ = __str__
class OrderedLinkedList:
def __init__(self):
self.head=None
self.tail=None
self.count = 0
def __str__(self):
temp=self.head
out=[]
while temp:
out.append(str(temp.value))
temp=temp.next
out=' '.join(out)
return ('Head:{}\nTail:{}\nList:{}'.format(self.head,self.tail,out))
__repr__=__str__
def add(self, value):
#write your code here
if self.head == None:
new_node = Node(value)
self.head = new_node
self.tail = self.head
self.head.setNext(self.tail)
if self.head.value > value:
new_node = Node(value)
new_node.value = value
new_node.next = self.head
self.head = new_node
else:
new_node = Node(value)
self.tail.setNext(new_node)
self.tail = new_node
self.count += 1
def pop(self):
#write your code here
if self.head == None:
return 'List is empty'
if len(self) == 1:
value = self.head.getValue()
self.head = None
self.tail = None
self.count = 0
return value
current = self.head
while current.next is not self.tail:
current = current.getNext()
value = self.tail.getValue()
self.tail = current
self.tail.next = None
self.count -= 1
return value
def isEmpty(self):
#write your code here
return self.head == None
def __len__(self):
#write your code here
return self.count
The only problem I have with it is that when I first use the function add it adds the number twice. Below is the outcome when I first call add every time after that it adds the number only once. How can I fix it so it only adds the first number once instead of twice.
>>> x=OrderedLinkedList()
>>> x.add(2)
>>> print(x)
Head:Node(2)
Tail:Node(2)
List:2 2
add(item) adds a new Node with value=item to the list making sure that the ascending order is preserved. It needs the item and returns nothing.
Yep, it adds the first number twice since you need fix a bug in your add method by adding an elif:
def add(self, value):
if self.head == None:
new_node = Node(value)
self.head = new_node
self.tail = self.head
# self.head.setNext(self.tail) ## remove to prevent infinity loop
elif self.head.value > value:
new_node = Node(value)
new_node.value = value
new_node.next = self.head
self.head = new_node
else:
new_node = Node(value)
self.tail.setNext(new_node)
self.tail = new_node
Since, if the head es None once the data is added then the next conditional always will execute one of the two parts on if or else.
class Node(object):
def __init__(self, data, next):
self.data = data
self.next = next
class LinkedList(object):
head = None
tail = None
def print_list(self):
node = self.head
while node:
print node.data,
node = node.next
def add_front(self, data):
node = Node(data, None)
if self.head is None:
self.head = self.tail = node
else:
self.tail.next = node
self.tail = node
def remove(self, index):
curr_node = self.head
prev_node = None
while curr_node and index>=0:
if index == 0:
if prev_node is not None:
prev_node.next = curr_node.next
else:
self.head = curr_node.next
index = index - 1
prev_node = curr_node
curr_node = curr_node.next
So, I wanted to implement a remove method using index in python but it does not seem to be working. I think I'm messing something with replacing the nodes but can't figure out which one. So a little help needed here.
Getting caught up in a solution to NoneType errors stemming from using my functions add and append in the below code to an empty Double_list class object. Best way to avoid?
class Dbl_Node:
def __init__(self, data):
self.data = data
self.next = None
self.prev = None
class Double_list:
def __init__(self): # Creates initial list w/ head and tail as None
self.head = None
self.tail = None
def add(self, item): # adds node to beginning/head of list
temp = self.head
self.head = Dbl_Node(item)
temp.prev = self.head
self.head.next = temp
def append(self, item): # adds node to end/tail of list
temp = self.tail
self.tail = Dbl_Node(item)
self.tail.prev = temp
temp.next = self.tail
You're initialising head and tail to None, but then trying to set prev and next members on them when inserting the first Dbl_Node.
def add(self, item):
temp = self.head # on the first call to "add", self.head is None
# (as set in __init__) so temp is now None
self.head = Dbl_Node(item) # create a new node and assign it to self.head
# this is fine
temp.prev = self.head # this says assign the new node in self.head to the "prev"
# member of temp, however temp is None so the temp.prev part
# throws the error
You should check for this case
def add(self, item): # adds node to beginning/head of list
temp = self.head
self.head = Dbl_Node(item)
if temp is not None:
temp.prev = self.head
An alternate solution is to start with "dummy" nodes for the head and tail:
def __init__(self):
self.head = Dbl_Node(None)
self.tail = Dbl_Node(None)
self.head.next = self.tail
self.tail.prev = self.head
And then insert items in between these nodes
def add(self, item):
temp = self.head.next
self.head.next = Dbl_Node(item)
temp.prev = self.head.next
self.head.next.next = temp
Although I find this tends to needlessly complicate things a bit.
def append(self, item): # adds node to end/tail of list
temp = self.tail
self.tail = Dbl_Node(item)
self.tail.prev = temp
temp.next = self.tail
This will always raise a NoneType exception because
self.tail is initially None then you assign a reference
to it (None) to temp and try to assign something to
None. Won't work.
YOu need to probably firstly assign a new object reference to self.tail
I am constructing a doubly linked list and I am struggling on construct a doubly linked list iterator method in PYTHON.
This is my code so far
class DoubleListNode:
def __init__(self,data):
self.data=data
self.prev = None
self.next= None
class ListIterator:
def __init__(self):
self._current = self.head
def __iter__(self):
return self
def next(self):
if self.size == 0 :
raise StopIteration
else:
item = self._current.data
self._current=self._current.next
return item
class DoublyLinkedList:
def __init__(self):
self.head= None
self.tail= None
self.size = 0
def add(self,data):
newnode= DoubleListNode(data)
self.size+=1
if self.head is None:
self.head = newnode
self.tail = self.head
elif data < self.head.data: # before head
newnode.next = self.head
self.head.prev= newnode
self.head= newnode
elif data > self.tail.data: # at the end
newnode.prev= self.tail
self.tail.next= newnode
self.tail=newnode
else:
curNode = self.head
while curNode is not None and curNode.data < data:
curNode=curNode.next
newnode.next= curNode
newnode.prev=curNode.prev
curNode.prev.next= newnode
curNode.prev=newnode
def remove(self,data):
curNode=self.head
while curNode is not None and curNode.data!= data:
curNode= curNode.next
if curNode is not None:
self.size -= 1
if curNode is self.head:
self.head= curNode.next
else:
curNode.prev.next=curNode.next
if curNode is self.tail:
self.tail=curNode.prev
else:
curNode.next.prev=curNode.prev
When I run a test it said TypeError: iteration over non-sequence. Did I do something wrong ?
As posted, the code doesn't initialize (i.e. self.head isn't defined).
But overall, you are on the right track. Take a look at the source for Python's collections.OrderedDict for a worked-out example of traversing a doubly linked list.
Here's a simplified example:
class Link:
def __init__(self, value, prev=None, next=None):
self.value = value
self.prev = prev
self.next = next
def __iter__(self):
here = self
while here:
yield here.value
here = here.next
def __reversed__(self):
here = self
while here:
yield here.value
here = here.prev
if __name__ == '__main__':
a = Link('raymond')
b = Link('rachel', prev=a); a.next=b
c = Link('matthew', prev=b); b.next=c
print 'Forwards:'
for name in a:
print name
print
print 'Backwards:'
for name in reversed(c):
print name
I think there are two important things to fix.
First, your DoublyLinkedList class doesn't have an __iter__ method. You probably want to create one that returns a ListIterator instance. Perhaps you're trying to do this manually, but this would be the normal approach.
Second, you need to fix the code in your ListIterator to work properly. Currently your __init__ method doesn't initialize things correctly, and your next method tries to access member variables like size that don't exist.
Here's an implementation that I think will work:
def ListIterator(object):
def __init__(self, node):
self.current = node
def __iter__(self):
return self
def next(self):
if self.current is None:
raise StopIteration()
result = self.current.data
self.current = self.current.next
return result
class DoublyLinkedList(object):
# all your current stuff, plus:
def __iter__(self):
return ListIterator(self.head)
As a side note, in your current code you're defining classes with no bases. This is fine in Python 3 (where object will be the base by default), but in Python 2 this will result in getting an "old-style" class. Old-style classes are deprecated, and you'll find that some language features won't work properly with them (though not any of the features involved in iteration, as far as I know). On the other hand, if you are already using Python 3 then you need to define a __next__ method in the iterator class, rather than next (without the underscores).
Here is an example for Doubly Linked List class.
class Node:
def __init__(self, val):
self.data = val
self.next = None
self.prev = None
class LinkedList:
def __init__(self):
self.head = None
self.tail = None
self.count = 0
def insert(self, val):
newNode = Node(val)
if self.count == 0:
self.head = newNode
self.tail = newNode
else:
self.head.prev = newNode
newNode.next = self.head
self.head = newNode
self.count += 1
def insertToEnd(self, val):
newNode = Node(val)
if self.count == 0:
self.head = newNode
self.tail = newNode
else:
self.tail.next = newNode
newNode.prev = self.tail
self.tail = newNode
self.count += 1
def search(self, val):
p = self.head
while p is not None:
if p.data == val:
return p
p = p.next
def delete(self, val):
curNode = self.head
while curNode != None:
if curNode.data == val:
if curNode.prev != None:
curNode.prev.next = curNode.next
else:
self.head = curNode.next
if curNode.next != None:
curNode.next.prev = curNode.prev
else:
self.tail = curNode.prev
self.count -= 1
curNode = curNode.next
def show(self):
s = ""
p = self.head
while p is not None:
s += str(p.data) + ' ';
p = p.next
print(s + "| count: " + str(self.count))
Based on what you post, may I suggest:
class ListIterator:
# other stuff ...
def __iter__(self):
while self._current:
yield self._current.data
self._current = self._current.next
self._current = self.head # Reset the current pointer
You don't have to implement next()
Update
Here is an example usage:
for data in myListIterator:
print data
# Without reset, the second time around won't work:
for data in myListIterator:
print data