Implementing append function in linked list in python - python

I am trying to write the list.append() operation in python. I implemented a linked list and it work fine. But I am not getting the last data item to be printed. When I try to print all the items in the list I get all the data value inside the node printed except the last one. I get 'None' printed instead of the value. I'm making some mistake in assigning the next pointer to 'None' in the newly added node. Need help in fixing.
Implementation of Node class and List class.
class Node:
def __init__(self,item):
self.data = item
self.next = None
def getData(self):
return self.data
def getNext(self):
return self.next
def setData(self,newItem):
self.data = newItem
def setNext(self, newNext):
self.next = newNext
class UnorderedList:
def __init__(self):
self.head = None
def isEmpty(self):
return self.head == None
def add(self,item):
temp = Node(item)
temp.setNext(self.head)
self.head = temp
def size(self):
count = 0
current = self.head
while current != None:
count = count + 1
current = current.getNext()
def append(self, item):
current = self.head
isEnd = False
newItem = Node(item)
while not isEnd:
if current.getNext() == None:
isEnd = True
else:
current = current.getNext()
current = current.setNext(newItem)
newItem = current.getNext()
def printList(self):
current = self.head
isEnd = False
while not isEnd:
if current.getNext() == None:
isEnd = True
else:
print current.getData()
current = current.getNext()
I create an object and pass values.
mylist = UnorderedList()
mylist.add(31)
mylist.add(77)
mylist.add(17)
mylist.add(93)
mylist.add(26)
mylist.add(54)
print(mylist.size())
mylist.append(12)
print(mylist.size())
mylist.append(15)
print(mylist.size())
print('\n')
print mylist.printList()
Output is:
6
7
8
54
26
93
17
77
31
12
None

The problem is you are doing
print(mylist.printList())
while printList() doesn't actually return anything. That's the last None printed there.
Hope this helps:
current = self.head
while(current!=None):
print(current.getData())
current=current.getNext()
This should be placed inside printlist.
And called this way :
mylist.printlist()
54
26
93
17
77
31
12
15
Edit :
I had also modified your append function to :
def append(self, item):
print("append",item)
current = self.head
isEnd = False
newItem = Node(item)
while not isEnd:
if current.getNext() == None:
isEnd = True
else:
current = current.getNext()
print("\Appending to",current.getData())
current.setNext(newItem)
current=current.getNext()
print("\tAppended",current.getData())

Related

Reversed double linked list by python

why can't print reversed this double linked list by python?
always print 6 or None
please can anyone help me fast to pass this task
///////////////////////////////////////////////////////////////////////////
class Node:
def __init__(self, data=None, next=None, prev=None):
self.data = data
self.next = next
self.previous = prev
sample methods==>
def set_data(self, newData):
self.data = newData
def get_data(self):
return self.data
def set_next(self, newNext):
self.next = newNext
def get_next(self):
return self.next
def hasNext(self):
return self.next is not None
def set_previous(self, newprev):
self.previous = newprev
def get_previous(self):
return self.previous
def hasPrevious(self):
return self.previous is not None
class double===>
class DoubleLinkedList:
def __init__(self):
self.head = None
self.tail = None
def addAtStart(self, item):
newNode = Node(item)
if self.head is None:
self.head = self.tail = newNode
else:
newNode.set_next(self.head)
newNode.set_previous(None)
self.head.set_previous(newNode)
self.head = newNode
def size(self):
current = self.head
count = 0
while current is not None:
count += 1
current = current.get_next()
return count
here is the wrong method ==>
try to fix it without more changes
def printReverse(self):
current = self.head
while current:
temp = current.next
current.next = current.previous
current.previous = temp
current = current.previous
temp = self.head
self.head = self.tail
self.tail = temp
print("Nodes of doubly linked list reversed: ")
while current is not None:
print(current.data),
current = current.get_next()
call methods==>
new = DoubleLinkedList()
new.addAtStart(1)
new.addAtStart(2)
new.addAtStart(3)
new.printReverse()
Your printReverse seems to do something else than what its name suggests. I would think that this function would just iterate the list nodes in reversed order and print the values, but it actually reverses the list, and doesn't print the result because of a bug.
The error in your code is that the final loop has a condition that is guaranteed to be false. current is always None when it reaches that loop, so nothing gets printed there. This is easily fixed by initialising current just before the loop with:
current = self.head
That fixes your issue, but it is not nice to have a function that both reverses the list, and prints it. It is better practice to separate these two tasks. The method that reverses the list could be named reverse. Then add another method that allows iteration of the values in the list. This is done by defining __iter__. The caller can then easily print the list with that iterator.
Here is how that looks:
def reverse(self):
current = self.head
while current:
current.previous, current.next = current.next, current.previous
current = current.previous
self.head, self.tail = self.tail, self.head
def __iter__(self):
node = self.head
while node:
yield node.data
node = node.next
def __repr__(self):
return "->".join(map(repr, self))
The main program can then be:
lst = DoubleLinkedList()
lst.addAtStart(1)
lst.addAtStart(2)
lst.addAtStart(3)
print(lst)
lst.reverse()
print(lst)

Remove Leading and Trailing Single Quote when String Formatting in Python

I'm trying to learn python so I decided to implement a Singly Linked List but I stumbled upon a weird problem.
As you could see from the screenshot above, the output when I'm trying to search for the index of a node has a leading and trailing single quote.
class Node:
next_node = None
def __init__(self, data):
self.data = data
def __repr__(self):
return "<Node data: %s>" % self.data
class LinkedList:
def __init__(self):
self.head = None
self.tail = None
def is_empty(self):
return self.head == None
def size(self):
current = self.head
count = 0
while current:
count += 1
current = current.next_node
return count
def append(self, data):
new_node = Node(data)
if self.is_empty():
self.head = new_node
else:
self.tail.next_node = new_node
self.tail = new_node
def search_node(self, key):
current = self.head
position = 0
while current:
if current.data == key:
# This returns with a leading and trailing single quote
return "<Node index: %s>" % position
else:
current = current.next_node
position += 1
return None
def search_index(self, index):
if index == 0:
return self.head
elif index == self.size() - 1:
return self.tail
else:
current = self.head
position = 0
while position < index:
current = current.next_node
position += 1
return current
def __repr__(self):
nodes = []
current = self.head
if self.is_empty():
return "<Empty>"
if self.size() == 1:
return "<Head: Tail: %s>" % current.data
while current:
if current is self.head:
nodes.append("<Head: %s>" % current.data)
elif current.next_node is None:
nodes.append("<Tail: %s>" % current.data)
else:
nodes.append("<%s>" % current.data)
current = current.next_node
return "-> ".join(nodes)
What's causing this behavior? I saw some articles about the repr function causing it but I'm not really sure.
I made some notes in your code that will hopefully help with identifying why your outputs are not consistent.
class LinkedList:
def __init__(self):
self.head = None < - node or None
self.tail = None < - node or None
def search_node(self, key): # <- function return will be str or None
current = self.head
position = 0
while current:
if current.data == key:
return "<Node index: %s>" % position # <-- Returning a string
else:
current = current.next_node
position += 1
return None # <--- Returning None
def search_index(self, index): # <- function returns node or None
if index == 0:
return self.head # <- returing node or None
elif index == self.size() - 1:
return self.tail # <- returning node or None
else:
current = self.head
position = 0
while position < index:
current = current.next_node
position += 1
return current # <- returning node or None
The __repr__(str) of a string will always have the quotes surrounding it.

Infinite loop while reversing a linked list in Python

So I have this code
class Node():
def __init__(self, data):
self.data = data
self.next = None
class LinkedList():
def __init__(self):
self.head = None
self.length = 0
def prepend(self, data):
new_node = Node(data)
new_node.next = self.head
self.head = new_node
self.length += 1
def print_list(self):
if self.head == None:
print('Empty')
else:
currentNode = self.head
while currentNode != None:
print(currentNode.data, end = ' ')
currentNode = currentNode.next
def reverse(self):
first = self.head
second = first.next
while second:
temp = second.next
second.next = first
first = second
second = temp
I prepend and then have a list of [8,7,11,6,5,10].
When I try to use the reverse function and try to print out I get infinite loop of 8 and 7. I'm not sure why. I thought the first already points to the self.head so that when it gets changed, the self.head gets changed as well. But its not the case. Could someone please help me with this?
Your reverse method is focussing on only the first two elements, and setting up cyclic references between them.
Here's the modified reverse() method, that works. (Note that the reverse() method contains an enclosed helper function called rev_(), which recurses through the linked list):
def reverse (self): #------------MODIFIED--------------
def rev_ (head):
rest = head.next
if rest is None:
return head
else:
reversed_rest = rev_(rest)
rest.next = head
head.next = None
return reversed_rest
if self.head is not None:
self.head = rev_(self.head)
Testing it out:
my_list = LinkedList()
my_list.print_list()
print()
my_list.reverse()
my_list.print_list()
print()
my_list.prepend(21)
my_list.print_list()
print()
my_list.reverse()
my_list.print_list()
print()
my_list.prepend(22)
my_list.prepend(23)
my_list.print_list()
print()
my_list.reverse()
my_list.print_list()
Output:
Empty
Empty
21
21
23 22 21
21 22 23

Python Circular Queue using Linked List

I'm trying to implement a circular queue (without limited buffer) in python.
When I call display after enqueue, it doesn't work. However, it works fine when called in other cases.
Its implementation is similar to the get_size function which works as expected.
Below is the implementation:
class Node(object):
def __init__(self, value):
self.value = value
self.next = None
class LinkedCircularQueue(object):
def __init__(self, head=None, tail=None):
self.head = head
self.tail = tail
def enqueue(self, item):
"""
Add the node to the back of the queue and set its next pointer to
self.head
"""
if self.tail is not None:
self.tail.next = item
else:
self.head = item
self.tail = item
item.next = self.head
return self.tail.value
def dequeue(self):
"""
Remove the oldest node (from the front) by copying the value and
making the preceding node as the new head
"""
if self.head is not None:
deleted = self.head.value
self.head = self.head.next
else:
deleted = None
print("Circular queue is empty !!")
return deleted
def display(self):
"""
Traverse from front to back and show elements
"""
front = self.head
back = self.tail
if front is not None and back is not None:
while back.next != front:
print(front.value, end=" ")
front = front.next
else:
print("Circular queue is empty !!")
def get_size(self):
"""
Traverse from front to back and count elements
"""
size = 0
if self.head is not None and self.tail is not None:
while self.tail.next != self.head:
size += 1
self.head = self.head.next
return size
def peek_front(self):
front = self.head
return front.value
def peek_back(self):
back = self.tail
return back.value
def is_empty(self):
first = self.head
last = self.tail
if first is None and last is None:
return True
else:
return False
def main():
# Initialize elements
element1 = Node(1)
element2 = Node(2)
element3 = Node(3)
element4 = Node(4)
element5 = Node(5)
linked_circular_queue = LinkedCircularQueue()
# Initial tests
linked_circular_queue.display()
print(linked_circular_queue.is_empty())
print(linked_circular_queue.get_size())
print()
# Test enqueue
linked_circular_queue.enqueue(element5)
linked_circular_queue.enqueue(element3)
linked_circular_queue.enqueue(element1)
linked_circular_queue.enqueue(element4)
linked_circular_queue.enqueue(element2)
linked_circular_queue.display() # doesn't work
print()
# Test dequeue
linked_circular_queue.dequeue()
linked_circular_queue.dequeue()
linked_circular_queue.display()
print()
# Test peek
print(linked_circular_queue.peek_front())
print(linked_circular_queue.peek_back())
print()
# Final tests
print(linked_circular_queue.is_empty())
print(linked_circular_queue.get_size())
if __name__ == '__main__':
main()
Current Output:
Circular queue is empty !!
True
0
1 4 2
1
2
False
3
Expected Output:
Circular queue is empty !!
True
0
5 3 1 4 2
1 4 2
1
2
False
3
Change the while loop from the display function to this:
while back != front:
print(front.value, end=" ")
front = front.next
print(back.value) # print(front.value) also works

How does a node with return self work?(Python)

So this is the node part of a singly linked list. I am not supposed to change the way it has been coded, but I dont know how this type of structure would work. Self.link cannot event be accessed to point towards another part of the list. Does anyone know how to work with such a Node class?
class Node:
def __init__(self, inval=None):
self.val = inval
if inval==None:
self.link = self
print (self)
def __str__(self):
if self.val == None:
return ''
else:
return str(self.val)
def __repr__(self):
return str(self)
Here is another implementation of the linked list, which has a slightly different styled node.
class LinkedList:
lock = 0
if lock == 0:
tempdata = None
def __init__(self, *args):
self.head = Node() # Node at the head of the list
self.current = None # Node currently pointed to by the iterator
self.count = 0
def insert(self, value):
NewNode =Node(value)
NewNode.link = self.head
self.head = NewNode
self.count += 1
def __iter__(self):
self.current = self.head
return self
def __next__(self):
self.current = LinkedList.tempdata
if LinkedList.lock == 0:
self.current = self.head
LinkedList.lock += 1
else:
pass
if self.current.value == None:
LinkedList.lock = 0
raise StopIteration
previous = self.current
self.current = self.current.link
LinkedList.tempdata = self.current
return previous
def __str__(self):
result = ''
self.current = self.head
while self.current.value is not None:
if self.current.link.value is None:
result += str(self.current.value)
else:
result += str(self.current.value) + ' -> '
self.current = self.current.link
return result
def search(self, value):
found = 0
temp = None
out= False
while found == 0:
try:
temp = LinkedList.__next__(self)
if temp.value == value:
found += 1
out = temp
except StopIteration:
pass
return out
def delete(self, value):
print ("hwta")
found = 0
temp = None
head = self.head
if head.value == value:
print ("Head")
if head.link.value != None:
self.head = head.link
else:
self.head = Node()
else:
while found == 0:
try:
temp = LinkedList.__next__(self)
if temp.link.value == value:
if temp.link.link.value == None:
temp.link = Node()
break
else:
temp.link = temp.link.link
print ("tails")
break
except StopIteration:
pass
def __repr__(self):
return str(self)
#a = Node()
#print(a) # 3
#b = Node("Hullo")
#print(b) # 'Hullo'
#lst = LinkedList()
#lst.insert(2)
#lst.insert(3)
#lst.insert(5)
#lst.insert(6)
#lst.insert(7)
#lst.insert(6)
#print(lst) # 5 -> 3 -> 2
#c = lst.search(2)
#print(c) # 3
#print(c.link) # 5
#lst.insert(2)
#print(lst.head.link.link) # 3
lst.delete(6)
print (lst)
#print(next(lst)) # should print 5, 3, 2 on separate lines
#lst.delete(2)
#print(lst) # 5 -> 3
#print(len(lst)) # 2
#for u in lst:
# print(u)
Nothing in the Node implementation that would prevent you from using it in a List class. Just pretend that the final three lines of Node.__init__() don't exist.
Here is one way to use the professor's Node in your List.
class Node:
def __init__(self, inval=None):
self.val = inval
if inval==None:
self.link = self
print (self)
def __str__(self):
if self.val == None:
return ''
else:
return str(self.val)
def __repr__(self):
return str(self)
class List:
def __init__(self):
self.head = None
def prepend(self, val):
head = Node(val)
head.link = self.head
self.head = head
def append(self, val):
if self.head is None:
self.prepend(val)
else:
p = self.head
while p.link is not None:
p = p.link
p.link = Node(val)
p.link.link = None
def __str__(self):
result = '<'
p = self.head
while p is not None:
result += str(p) + ', '
p = p.link
result += '>'
return result
l = List()
l.append(3)
l.prepend(2)
l.append(4)
l.prepend(1)
l.append(5)
print(str(l))
And here is the result:
<1, 2, 3, 4, 5, >

Categories