I am trying to created a linked list. However, the following code keeps printing only the last element of the list. Is there an error in my code? I think the problem lies in the "insert" method. I am not able to figure out why though.
import sys
import io
string = """4
2
3
4
1"""
sys.stdin = io.StringIO(string)
class Node:
def __init__(self, data):
self.data = data
self.next = None
class Solution:
def display(self, head):
current = head
while current:
print(current.data, end=' ')
current = current.next
# TODO: Code only prints the last element of data
def insert(self, head, data):
if head == None:
head = Node(data)
return head
else:
head.next = Node(data)
return head.next
mylist = Solution()
T = int(input())
head = None
for i in range(T):
data = int(input())
head = mylist.insert(head, data)
mylist.display(head)
The problem is you're losing the reference to the head of the list. You must keep the head and insert the new item at the end of the list
def insert(self,head,data):
if head == None:
head = Node(data)
else:
current = head
while current.next != None:
current = current.next
current.next = Node(data)
return head
You only keep a reference to the end of the chain (head.next), so yes, you'll only be able to display that last element.
You'll need to keep a reference to the first element (the real head):
mylist = Solution()
T = int(input())
current = head = None
for i in range(T):
data = int(input())
current = mylist.insert(head, data)
if head is None:
head = current
Related
I am trying to remove the kth element from the END of a linked list. Here is my code
class LinkedList:
def __init__(self, value):
self.value = value
self.next = None
def removeKthNodeFromEnd(head, k):
if k == 0 or head is None:
return
temp = head
while temp is not None and k > 1:
temp = temp.next
k -= 1
if temp is None or k > 1:
return head
trailing = None
leading = head
while temp.next is not None:
trailing = leading
leading = leading.next
temp = temp.next
if trailing is None:
head = head.next
else:
trailing.next = leading.next
head = LinkedList(0)
head.next = LinkedList(1)
head.next.next = LinkedList(2)
head.next.next.next = LinkedList(3)
head.next.next.next.next = LinkedList(4)
head.next.next.next.next.next = LinkedList(5)
head.next.next.next.next.next.next = LinkedList(6)
head.next.next.next.next.next.next.next = LinkedList(7)
head.next.next.next.next.next.next.next.next = LinkedList(8)
head.next.next.next.next.next.next.next.next.next = LinkedList(9)
removeKthNodeFromEnd(head, 10)
while head is not None:
print(head.value)
head = head.next
But this does not work and prints out all the values in the linked list from 0 to 9. Why is this the case? If the node to delete is the head node which I check by checking trailing is None, then I update head = head.next. I am changing head to be the next node. I can return head after this update and the result of head = removeKthNodeFromEnd(head, k) will give me the desired output but why can't I do it the other way without returning anything? For instance in my solution I can get rid of any element in between the first and last node including the last and works just fine. The original head gets updated and node gets removed. But when trying to update the head node head = head.next it does not work.
One way I achieved this is by doing the following...
if trailing is None:
head.value = head.next.value
head.next = head.next.next
But why must I use the values? To me this seems the same as
if trailing is None:
head = head.next
head.next = head.next.next
but does not work
It doesn't work because head in that function is a local name. Assigning to a local variable never does anything to other variables, even not when they happen to have the same name (like the global head).
The "trick" you have by moving a linked list value with head.value = head.next.value will not work when the list only has one node.
One way to do this, is to return the (potentially modified) value of head, and expect the caller to assign this back to their own head variable.
So:
in removeKthNodeFromEnd make sure all return statements are like return head, and that you add a return head at the very end. In short, removeKthNodeFromEnd should always return head.
in the main program, change the call to head = removeKthNodeFromEnd(head, 10)
That will solve your issue.
Here are some ideas to make your code more elegant:
Create a separate class for maintaining the head of the linked list
Improve the constructor, so that it is easier to initialise a linked list
Add an iterator so it is easier to print a linked list
class Node: # renamed
def __init__(self, value, nxt=None):
self.value = value
self.next = nxt # is now an argument
class LinkedList: # added
def __init__(self, *values):
self.head = None
if values: # populate the list with values
for value in reversed(values):
self.push_front(value)
def push_front(self, value):
self.head = Node(value, self.head)
def __iter__(self):
node = self.head
while node:
yield node.value
node = node.next
def removeKthNodeFromEnd(self, k):
if k <= 0:
return
temp = self.head
for _ in range(k):
if not temp: # k is out of range
return
temp = temp.next
if temp:
trailing = self.head
while temp.next:
trailing = trailing.next
temp = temp.next
trailing.next = trailing.next.next
else:
self.head = self.head.next
lst = LinkedList(*range(10))
print(*lst)
lst.removeKthNodeFromEnd(0)
print(*lst)
And if you maintain a size attribute, you can do:
class LinkedList: # added
def __init__(self, *values):
self.head = None
self.size = 0
if values:
for value in reversed(values):
self.push_front(value)
def push_front(self, value):
self.head = Node(value, self.head)
self.size += 1
def __iter__(self):
node = self.head
while node:
yield node.value
node = node.next
def removeAt(self, k):
if 1 < k <= self.size:
trailing = self.head
for _ in range(k - 2):
trailing = trailing.next
trailing.next = trailing.next.next
elif 1 == k <= self.size:
self.head = self.head.next
def removeKthNodeFromEnd(self, k):
self.removeAt(self.size + 1 - k)
I'm trying to convert a string into a doubly linked list. I want to be able to traverse it, find a match, and then insert another linked list at a certain position. However, I'm having trouble with my pointers. I have 'current.prev', 'current', and 'current.next' pointers that should all be pointing at the nodes in that order. Instead, my .prev and current pointers always point to the same thing. I need to be able to point at the different parts of the linked list, otherwise I won't be able to traverse back to a certain spot so I can insert a new linked list.
this is the code that creates doubly linked lists for me:
#-----------------------doubly-linked-lists-----------------------#
class NodeD:
def __init__(self, data):
self.data = data
self.next = None
self.prev = None
class DoublyLL:
def __init__(self):
self.head = None
def append(self, new_data):
new_node = NodeD(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
new_node.prev = last
return
def printList(self, node):
while node:
print(node.data, end=""),
last = node
node = node.next
this is the code that makes a string into a linked list:
#making-linked-lists-from-strings#
def dnaToLL(dnainput):
dnaLL = DoublyLL()
head = NodeD(dnainput[0])
dnaLL.head = head
current = dnaLL.head
for i in range(1, len(dnainput)):
current.prev = current
current = current.next
current.next = NodeD(dnainput[i])
return dnaLL
I've been using this to test where the pointers are pointing:
dnaLL = dnaToLL(DNA)
dnaLL = dnaLL.head
print(dnaLL.prev.data +dnaLL.data+dnaLL.next.data)
but with this input:
S1 = "neho"
DNA = "imfinehowru"
I get this output:
iim
any idea where I've gone wrong? I am assuming it's where I've tried to make strings into doubly linked lists, but any other order that I put the pointers in gives me errors.
Thank you for your help!
The problem is that whe you do current.prev = current, you're saying "the previous node is the current node" - not the actual previous node.
Keep in mind that the first node in the list should have .prev = None. You'd only want to set .prev for future nodes. This modification should fix your dnaToLL() function:
def dnaToLL(dnainput):
dnaLL = DoublyLL()
head = NodeD(dnainput[0])
dnaLL.head = head
current = dnaLL.head
for i in range(1, len(dnainput)):
# note how the order is changed
current.next = NodeD(dnainput[i])
current.next.prev = current
current = current.next
return dnaLL
This is the question I'm stuck at!
The problem is the code is not generating any output. (it doesn't print anything.)
My guess is the LinkedList is not getting modified at all!
I have only defined the two functions insertAtBeginning(head,x) and insertAtEnd(head,x). The rest of the code is from GeeksForGeeks.
class Node:
def __init__(self,data):
self.data=data
self.next=None
# function inserts data x in front of list and returns new head
def insertAtBegining(head,x):
# code here
global a
if head is None:
a.head = Node(x)
# head.next = None
else:
node = Node(x)
node.next = a.head
a.head = node
# head.next = node
# function appends data x at the end of list and returns new head
def insertAtEnd(head,x):
# code here
global a
if head is None:
a.head = Node(x)
# head.next = None
else:
node = Node(x)
current = head
while current.next is not None:
current = current.next
current.next = node
# node.next = None
#{
# Driver Code Starts
class Node:
def __init__(self,data):
self.data=data
self.next=None
class LinkedList:
def __init__(self):
self.head=None
def printList(head):
while head:
print(head.data,end=' ')
head=head.next
print()
if __name__ == '__main__':
t=int(input())
for cases in range(t):
n=int(input())
a=LinkedList()
nodes_info=list(map(int,input().split()))
for i in range(0,len(nodes_info)-1,2):
if(nodes_info[i+1]==0):
a.head = insertAtBegining(a.head,nodes_info[i])
else:
a.head = insertAtEnd(a.head,nodes_info[i])
printList(a.head)
# } Driver Code Ends
I hope I have provided all the necessary information. Please help.
It looks like insertAtBegining is expected to return the new head of the linked list, whereas your implementation doesn't look like it returns anything at all.
Find the frequency of numbers using linkedlist.
Getting SIGTSTP - time limit exceed error while running the below code. Can anyone help me where am I getting it wrong?
class Element(object):
def __init__(self,value):
self.value = value
self.next = None
class LinkedList(object):
def __init__(self, head = None):
self.head = head
def append(self, new):
current = self.head
if self.head:
while current.next:
current = current.next
current.next = new
else:
self.head = new
def traverse(self):
current = self.head
while current != None:
print(current.value)
current = current.next
arr = list(map(int, input().split()))
ll = LinkedList()
for i in arr:
e = Element(i)
ll.append(e)
ll.traverse()
def frequency(a):
current = a.head
while current != None:
count = 1
while current.next != None:
if current.value == current.next.value:
current+=1
if current.next.next != None:
current.next = current.next.next
else:
current.next = None
print(str(current.value)+" : " + str(count))
current = current.next
frequency(ll)
Everything looks fine except frequency. You will need to keep two references, one to the current element and the other will traverse the remainder of the list, starting from current. Does that give you something to go on?
Note too that your current implementation will modify the underlying linked list, while you can indeed do "skipping" with the pointers to prevent listing the same element multiple times, it is imo preferable to avoid modifying the underlying structure in this way.
Given a linked list, write a function to reverse every k nodes (where k is an input to the function).
Examples:
Inputs: 1->2->3->4->5->6->7->8->NULL and k = 3
Output: 3->2->1->6->5->4->8->7->NULL.
Inputs: 1->2->3->4->5->6->7->8->NULL and k = 5
Output: 5->4->3->2->1->8->7->6->NULL.
This is the Code:
# Node class
class Node:
# Constructor to initialize the node object
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
# Function to initialize head
def __init__(self):
self.head = None
def reverse(self, head, k):
current = head
Next = None
prev = None
count = 0
# Reverse first k nodes of the linked list
while(current is not None and count < k):
Next = current.next
current.next = prev
prev = current
current = Next
count += 1
# next is now a pointer to (k+1)th node
# recursively call for the list starting
# from current . And make rest of the list as
# next of first node
if Next is not None:
head.next = self.reverse(Next, k)
# prev is new head of the input list
return 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
# Driver program
llist = LinkedList()
llist.push(9)
llist.push(8)
llist.push(7)
llist.push(6)
llist.push(5)
llist.push(4)
llist.push(3)
llist.push(2)
llist.push(1)
print "Given linked list"
llist.printList()
llist.head = llist.reverse(llist.head, 3)
print "\nReversed Linked list"
llist.printList()
On my computer, this code gives me error saying "LinkedList class has no attribute next" => the error in this statement "Next = current.next" . On Geeks for Geeks the code is running fine. Also on all the online IDEs the code is running fine. So is it something wrong with my device or the code should not run ?