Insertion before a node in Doubly link list - python

i'm trying to insert a node before a node into doubly linked list.After performing the operation i'm not getting the correct results.
class createnode:
def __init__(self,data):
self.data=data
self.next=None
self.prev=None
class Unordered_list:
def __init__(self):
self.head=None
######Insertion at the starting###
def buildlst(self,data):
node=createnode(data)
if self.head is None:
self.head=node
else:
node.next=self.head
node.prev=None
self.head=node
#######INsertion at the end####
def buildlstend(self,data):
node=createnode(data)
ptr=self.head
while(ptr.next):
ptr=ptr.next
ptr.next=node
ptr=node.prev
#######INsertion before some node i.e searched node####
def insertbeforenode(self,data,srch_data):
node=createnode(data)
ptr=self.head
while(ptr):
if ptr.data==srch_data:
node.prev=ptr.prev
node.next=ptr
ptr.prev=node
ptr=ptr.next
########Printitng the list########
def printlist(self):
temp=self.head
while(temp):
print(temp.data)
temp=temp.next
A=Unordered_list()
A.buildlst(10)
A.buildlst(20)
A.buildlstend(30)
A.printlist()
print("Here i will insert a new node 50 before 10")
A.insertbeforenode(50,10)
A.printlist()
Mylist look some what like 20,10,30.I want to have the new node before 10.but it prints me the same results.Have been through this link Inserting a node before a given node in doubly linked list .My program is in python so couldn.t collect much from it.
insertbeforenode is my function from where i'm making a call.

Python supports a built-in mechanism to work with lists, you could easily do something like this:
list = []
list.append(10)
list.insert(0, 20)
list.append(30)
list.insert(1, 50)
See the official documentation for more examples https://docs.python.org/3/tutorial/datastructures.html.
Anyway if you want to program a double linked list by your self I have made some changes to your code:
class createnode:
def __init__(self, data):
self.data = data
self.next = None
self.prev = None
class Unordered_list:
def __init__(self):
self.head = None
def buildlst(self, data):
node = createnode(data)
if self.head is None:
self.head = node
else:
node.next = self.head
self.head.prev = node # <---
# node.prev = None <---- this is not necessary
self.head = node
def buildlstend(self, data):
node = createnode(data)
ptr = self.head
while ptr.next:
ptr = ptr.next
ptr.next = node
node.prev = ptr # <---
def insertbeforenode(self, data, srch_data):
if srch_data == self.head.data: # <-- if you try to insert before the head
self.buildlst(data)
else:
node = createnode(data)
ptr = self.head
while ptr:
if ptr.data == srch_data:
node.prev = ptr.prev
node.next = ptr
ptr.prev = node
node.prev.next = node # <--
break # <--- when you find your node you have to quit from the loop
else:
ptr = ptr.next
def printlist(self):
temp = self.head
while (temp):
print(temp.data)
temp = temp.next
I have put an arrow (# <--) where I made the changes. There were a couples of mistakes on working with pointers and others inaccuracies. Please try this and let me know!

Related

Python : I am not able to prepend a Value in a Singly Linked list

Code written in python:
prepend Function is supposed to add a value to the start of the Linked List
display Function is supposed to display the linked list in a List format in python
fromarr Function is supposed to add new nodes to the linked list
class Node:
def __init__(self,value=None):
self.value = value
self.next = None
class SinglyLL:
def __init__(self):
self.head = Node()
self.tail = Node()
def prepend(self,value):
newnode = Node(value)
newnode.next = self.head
self.head = newnode
def append(self,data):
newnode = Node(data)
if self.head is None:
self.head = newnode
return
cur = self.head
while cur.next != None:
cur = cur.next
cur.next = newnode
newnode.next = None
def display(self):
lis = []
cur = self.head
while cur.next != None:
cur = cur.next
lis.append(cur.value)
return lis
def fromarr(self,list):
for i in list:
temp = Node(i)
self.append(temp.value)
newsll = SinglyLL()
newsll.fromarr([1,2,3,4,5])
newsll.prepend(10)
print(newsll.display())
Expected output : [10,1,2,3,4,5]
Actual Output: [None,1,2,3,4,5]
well you are initalising your head with a empty node, and displaying values from self.head.next, so instead of setting element at position 0 you need to set element at position 1.
Adding below code for prepend method
class Node:
def __init__(self,value=None):
self.value = value
self.next = None
class SinglyLL:
def __init__(self):
self.head = Node()
self.tail = Node()
def prepend(self,value):
newnode = Node(value)
if self.head is None:
self.head = newnode
else:
tmp = self.head.next
self.head.next = newnode
newnode.next = tmp
def append(self,data):
newnode = Node(data)
if self.head is None:
self.head = newnode
return
cur = self.head
while cur.next != None:
cur = cur.next
cur.next = newnode
newnode.next = None
def display(self):
lis = []
cur = self.head
while cur.next != None:
cur = cur.next
lis.append(cur.value)
return lis
def fromarr(self,list):
for i in list:
temp = Node(i)
self.append(temp.value)
newsll = SinglyLL()
newsll.fromarr([1,2,3,4,5])
newsll.prepend(10)
print(newsll.display())
Your code has a mix of several approaches to organise a linked list data structure, but they are not compatible:
Your constructor creates a dummy node for the head attribute, which could be an approach when you intend to append all data nodes after that dummy node. The display method is in line with that approach as it doesn't include the value of the dummy node in the result. But the prepend nor the append method use that approach as they treat the head node as a data node.
Your constructor creates a dummy node for the tail attribute. This is an approach that might be used for a doubly linked list, but is not useful for a singly linked list, as the process to append a new node at the end of the list cannot take benefit from this reference.
Although the constructor defines a tail attribute none of the other methods make use of it, nor update it when necessary.
Some other remarks:
It is odd that the display method does not display anything. It would be more appropriate to have an __iter__ method instead which would yield the linked list's values.
fromarr is not a very good name for a method that accepts a list.
It is not intuitive that this is an instance method, as its name suggests that it will create a new list from those values, but you actually need to first create a linked list instance yourself, and then call this method. I would suggest to drop this method and extend the constructor with optional arguments which will be used to populate the constructed linked list.
list is a bad name for a parameter as this name is already in use by native Python.
It would be nice if the Node constructor would accept an optional argument for defining the next attribute.
Here is an update of your code that takes those points into account, and which uses the approach where:
A tail attribute is set and used
No dummy nodes are created
class Node:
def __init__(self, value=None, nxt=None):
self.value = value
self.next = nxt
class SinglyLL:
def __init__(self, *values):
# Don't create nodes here
self.head = self.tail = None
# Allow immediate population from arguments
for value in values:
self.append(value)
def prepend(self,value):
self.head = Node(value, self.head)
self.tail = self.tail or self.head
def append(self, data):
if not self.tail:
self.prepend(data)
else:
self.tail.next = self.tail = Node(data)
def __iter__(self):
cur = self.head
while cur:
yield cur.value
cur = cur.next
newsll = SinglyLL(1,2,3,4,5)
newsll.prepend(10)
print(list(newsll)) # [10, 1, 2, 3, 4, 5]

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)

calling a method in another method errors

class Node:
def __init__(self, data):
self.data = data
self.ref = None
class LinkedList:
def __init__(self):
self.head = None
def show(self):
if self.head is None:
print("This linked lists is empty")
else:
currentnode = self.head
while currentnode is not None:
print(currentnode.data, end=" --> ")
currentnode = currentnode.ref
def addelement(self, value):
newnode = Node(value)
newnode.ref = self.head
self.head = newnode
def lenofll(self , i = 0):
while self.head is not None:
i = i +1
self.head = self.head.ref
return i
def middle(self):
i = 0
lent = self.lenofll()
if self.head is None: # self.head changed to None after calling lenofll method.
print("linked list is empty")
I wanted to get the length of linked lists in the middle method. But as I called self.lenofll(), it changed the self.head to None.
What can I do to fix this?
Indeed, doing self.head = self.head.ref modifies the head. You should not make any modifications to self.head in a method whose job is just to search in the list -- without modifying anything to it.
As you can see, that method keeps looping until self.head is not None is not true, i.e. when self.head is None. No wonder that self.head is None after running this method!
Use a local variable for this iteration instead:
def lenofll(self, i = 0):
node = self.head # use local variable
while node is not None:
i += 1
node = node.ref
return i

Add Node function not working singly linked list python

I'm a Noob, struggling to understand and implement a singly linked list, that adds items at the tail. I believe the only code that is not working is the add function, which I can't figure out the logic for. I believe I want to set the first node to be the head, and then insert each other element at the tail, changing the pointer for head to point to the 2nd item when adding it, then the pointer for the 2nd item to point to the third etc., but can't figure out how to go about coding that (to deal with an unknown number of strings, here 3 for simplicity.
strings = ["one", "two", "three"]
class Node:
def __init__(self,data,nextNode=None):
# populate the Node, with data and pointer
self.data = data
self.nextNode = nextNode
def getData(self):
# method to get value of this node
return self.data
def setData(self,val):
# set value of node to val
self.data = val
def getNextNode(self):
# get the pointer to the next node
return self.nextNode
def setNextNode(self,val):
# set pointer to the next node
self.nextNode = val
class LinkedList:
def __init__(self, head = None, tail = None):
# initial properties of linked list, size 0
self.head = head
self.tail = tail
self.size = 0
def getSize(self):
# get size of linked list
return self.size
def addNode(self,data):
# Head should point to first node, which will have a value, and a Null pointer
if (self.size == 0):
newNode = Node(data, self.tail)
self.head.getNextNode() = newNode
else:
# All additional nodes should be inserted at tail, and with the pointers for the prior nodes changed to point to the new node
newNode = Node(data, self.tail)
self.tail = newNode
self.size += 1
return True
def printNode(self):
curr = self.head
while curr:
print(curr.data)#, curr.nextNode)
curr = curr.getNextNode()
mylist = LinkedList()
for i in strings:
mylist.addNode(i)
mylist.printNode()
# desired output: Head -> one --> two --> three/Tail
There were many little mistakes, please find them in code below. And let me know if you don't understand something.
One important change is a new node shouldn't have access to its next node. Its already the last node, so there can't be any node next to it. Also please pay close attention to else block of addNode function.
strings = ["one", "two", "three","four","five"]
class Node:
def __init__(self,data):
# populate the Node, with data and pointer
self.data = data
self.nextNode = None
def getData(self):
# method to get value of this node
return self.data
def setData(self,val):
# set value of node to val
self.data = val
def getNextNode(self):
# get the pointer to the next node
return self.nextNode
def setNextNode(self,val):
# set pointer to the next node
self.nextNode = val
class LinkedList:
def __init__(self, head = None, tail = None):
# initial properties of linked list, size 0
self.head = head
self.tail = tail
self.size = 0
def getSize(self):
# get size of linked list
return self.size
def addNode(self,data):
# Head should point to first node, which will have a value, and a Null pointer
if (self.size == 0):
self.head = Node(data)
self.tail = self.head
self.size = 1
else:
# All additional nodes should be inserted at tail, and with the pointers for the prior nodes changed to point to the new node
newNode = Node(data)
self.tail.nextNode = newNode
self.tail = newNode
self.size += 1
return True
def printNode(self):
curr = self.head
while curr:
print(curr.data)#, curr.nextNode)
curr = curr.getNextNode()
mylist = LinkedList()
for i in strings:
mylist.addNode(i)
mylist.printNode()

constructing a Queue linked list using only one head pointer

I'm trying to construct a Queue linked list using only a head pointer (no tail).
but i cant seem to enqueue at the end of the list.
example: at the moment the code will: c -> b -> a, however i would like reverse it a -> b -> c.
class Node:
'''A node for a linked list.'''
def __init__(self, initdata):
self.data = initdata
self.next = None
class Queue(object):
def __init__(self):
self.head = None
def enqueue(self, item):
"""Add an item onto the tail of the queue."""
if self.head == None:
temp = Node(item)
temp.next = self.head
self.head = temp
else:
current = self.head
while current != None:
current = current.next
if current == None:
temp = Node(item)
temp.next = current
current = temp
def dequeue(self):
if self.head == None:
raise IndexError("Can't dequeue from empty queue.")
else:
current_first = self.head
current = self.head.next
return current_first.data
This should do it:
class Node:
'''A node for a linked list.'''
def __init__(self, initdata):
self.data = initdata
self.next = None
class Queue(object):
def __init__(self):
self.head = None
def enqueue(self, item):
"""Add an item onto the tail of the queue."""
if self.head is None:
self.head = Node(item)
else:
current = self.head
while current.next is not None:
current = current.next
current.next = Node(item)
def dequeue(self):
if self.head is None:
raise IndexError("Can't dequeue from empty queue.")
else:
first = self.head
self.head = self.head.next
return first.data
Besides some logic fixes (we need to create a new node and store it in current.next, current is just a variable pointing to a node), note we use is operator for testing for None and Node constructor to set data (so we can create and assign new nodes without temp var).
For example:
q = Queue()
q.enqueue('a')
q.enqueue('b')
q.enqueue('c')
print(q.dequeue())
print(q.dequeue())
print(q.dequeue())
Outputs:
a
b
c
Btw, note that such structure requires O(N) insertion time and O(1) deletion (pop) time. Double-ended queue (like the standard collections.deque) will do both insertion and deletion in constant time.

Categories