Thank you, Gowtham! I'm really thrilled to hear that. Glad to hear that my videos have found some utility for you. Thanks for watching and for your comment. Cheers!
This is such an awesome series for interview prep!! Just curious, does the order in which you reassign the pointers affect the behavior of the program?
Cheers! If you enjoyed and benefited from my content, please consider liking the video and subscribing to the channel for more content like this. If you would like to support the content creation on this channel please consider unblocking ads when watching my videos as this is how I support my time to make content. I hope to be putting out more similar videos soon! And yes, order does matter.
Cheers! If you enjoyed and benefited from my content, please consider liking the video and subscribing to the channel for more content like this. If you would like to support the content creation on this channel please consider unblocking ads when watching my videos as this is how I support my time to make content. I hope to be putting out more similar videos soon!
Cheers! If you enjoyed and benefited from my content, please consider liking the video and subscribing to the channel for more content like this. If you would like to support the content creation on this channel please consider unblocking ads when watching my videos as this is how I support my time to make content. I hope to be putting out more similar videos soon!
Fantastic series! Thank yo so much. I am having trouble understanding the add node before/after methods for the doubly linked lists. When I wrote my own methods, I re-assigned four pointers for the cases where a node is actually being inserted into the list (not head or tail). For example, for the add_node_after method, the next and prev pointers for the new node must be set. In addition, the previous node needs its next pointer updated and the next node needs its prev pointer updated. The code as written in GitHub only reset three of these pointers for both the add_nod_after and add_node_before methods. Am I missing something?
Indeed it is a very nice tutorial! I just suggest one thing if you change the sequential number which you are adding then you can not insert the number where you want. Probably you may add another instance to the class for indexing the elements of the linked list. In this case, you may add a number where you want. Probably I am misunderstanding your method, Here is what I want to say. dllist.append(1) dllist.append(2) dllist.append(3) dllist.append(4) dllist.print_list() dllist. insert_after_node(2,11) 2 will be added between the 2 and 3. Let's think about it if we change the numbers you appended. It is a linked list before insertion. We may change 20,30,54,24 something like this. or we don't know the exact number but we know the node is not empty. In this case, we may add another instance that could be indexing the linked list. The "key" will be equal to the "index" of the linked list elements. I hope this is clear the confusion.
Great video as it usually is! By the way, how come you didn't put 'new_node.prev = cur' in the add_after function and 'new_node.prev = prev' in the add_before function? Thanks!
In the methods/functions 'add_after_node' and 'add_before_node' there should be return in the elif right ? Otherwise we may be traversing the doubly linked list for no reason even after adding the new node
@@LucidProgramming Hi - These are excellent tutorials and I used them - to code along and to learn about doubly linked list. However learning means - I have print statements everywhere to understand. What I notice is that after adding a node - using either 'add_before_node' or 'add_after_node' - the while loop still loops through the entire linked list which I presume one does not want. Check it out - add two nodes with same data - and use one of the methods. You will notice that it will add the node twice. However I think after adding the first time it should exit out of the loop.
@@VidyaBhandary Oh okay, thanks for providing more information on this. I think I see what you're saying, and yes, you could have an early exit condition to prevent from needlessly traversing the list. Thanks for pointing that out!
Awesome! I haven't look the video so not sure if you explained correctly but missed in the solution. After adding a node the list is no more remain a double linked list as you missed attaching previous of newly added node. To fix in case of add_after_node, add new_node.prev = cur after new_node.next = nxt.
Just an observation -- If key is repeated in the data,the new element is added before/after every occurance of the key instead of just the first occurance. DL = 1,2,1,2 and new_elem = 9; output = 1,9,2,1,9,2. i don't know if u intended to do that.. Anyways great videos..Lots of Thanks..
Is this code okay ?: def middle(self,index,data): n = input("Do you wish to add a node before the head (Y/N) ") if n == "Y": print("Then use the prepend function ") newnode = Node(data) cur = self.head count = 0 while cur: prev = cur cur = cur.next if count == index: prev.next = newnode newnode.prev = prev newnode.next = cur cur.prev = newnode return count+=1
@@akashvenugopal2489 The "if" statement won't effect the output, but it's just a weird thing to ask the user in that place that you're asking it. The flow there just seems strange to me.
Alternate implementation for after node, before a node can be implemented in the same way. class Node: def __init__(self,data): self.data = data self.prev = None self.next = None class DoublyLinkedList: def __init__(self): self.head = None def append(self,data): #Check if list is empty or not new_node = Node(data) if self.head is None: self.head = new_node return #Loop though the list and find the last node curr = self.head while curr.next: curr = curr.next curr.next = new_node def print_list(self): curr = self.head while curr: print(curr.data) curr = curr.next def after_node(self,after,data): new_node = Node(data) #If list is empty if self.head is None: self.head = new_node else: curr_node = self.head while not curr_node.next is None and curr_node.data != after: curr_node = curr_node.next #Check if search node is present or not if curr_node.data != after: print(f'{after} node is not present in the list') else: #Check if it is the last node if curr_node.next is None: curr_node.next = new_node new_node.prev = curr_node else: next_node = curr_node.next curr_node.next = new_node new_node.next = next_node new_node.prev = curr_node new_node.prev = new_node
Thank you 👌 def print_links(self): if not self.head: return "Linked List is Empty" else: return self.__print_helper_links(self.head) def __print_helper_links(self, head): # Base Case: if not head.next: return F"({str(head.data)})" + F" Previous: {head.previous.data} |" \ F" Next: {head.next.dataif head.next else head.next}" else: return F"({str(head.data)})" +\ F" Previous: {head.previous.data if head.previous else head.previous } |" \ F" Next: {head.next.data} " +\ " " + self.__print_helper_links(head.next) I implemented this additional function within the Doubly-Linked List class, this way I have easier time seeing all values, their previous values (if any) and next values (if any). Thought of sharing it with you guys.
sorry how self.data == key I think is wrong it's not logic we must change self.data with traversing until with the index if we changing instances with other values the insert after node doesn't work but instead of video is good and so simply
Sir great tutorial ever... I don't watch such a great tutorial before that.. Sir please continue advance tutorials if possible..
Sincerely appreciate that. If I get back to having the time, I'd love to start making videos again. Cheers!
Your tutorials are making me love Data Structures again.. Thank you!
Thank you, Gowtham! I'm really thrilled to hear that. Glad to hear that my videos have found some utility for you. Thanks for watching and for your comment. Cheers!
such a wonderful explanation maan
you really deserve respect🙌
Very much appreciated--thank you!
Subscribed! You are great in explaining by the way!
Thank you, Prafful! :)
Keep it up love those simple explanations! thank you!
Thank you, Pranay'z'! I appreciate the comment. Thanks for watching, and have a nice day.
This is such an awesome series for interview prep!! Just curious, does the order in which you reassign the pointers affect the behavior of the program?
Cheers! If you enjoyed and benefited from my content, please consider liking the video and subscribing to the channel for more content like this. If you would like to support the content creation on this channel please consider unblocking ads when watching my videos as this is how I support my time to make content. I hope to be putting out more similar videos soon!
And yes, order does matter.
Amazing teaching! Thankyou so much.
Cheers! If you enjoyed and benefited from my content, please consider liking the video and subscribing to the channel for more content like this. If you would like to support the content creation on this channel please consider unblocking ads when watching my videos as this is how I support my time to make content. I hope to be putting out more similar videos soon!
The way you explain concepts .....VERY NICE....#LucidProgrammingRocks
Cheers! If you enjoyed and benefited from my content, please consider liking the video and subscribing to the channel for more content like this. If you would like to support the content creation on this channel please consider unblocking ads when watching my videos as this is how I support my time to make content. I hope to be putting out more similar videos soon!
Fantastic series! Thank yo so much. I am having trouble understanding the add node before/after methods for the doubly linked lists. When I wrote my own methods, I re-assigned four pointers for the cases where a node is actually being inserted into the list (not head or tail). For example, for the add_node_after method, the next and prev pointers for the new node must be set. In addition, the previous node needs its next pointer updated and the next node needs its prev pointer updated. The code as written in GitHub only reset three of these pointers for both the add_nod_after and add_node_before methods. Am I missing something?
Indeed it is a very nice tutorial! I just suggest one thing if you change the sequential number which you are adding then you can not insert the number where you want. Probably you may add another instance to the class for indexing the elements of the linked list. In this case, you may add a number where you want.
Probably I am misunderstanding your method, Here is what I want to say.
dllist.append(1)
dllist.append(2)
dllist.append(3)
dllist.append(4)
dllist.print_list()
dllist. insert_after_node(2,11)
2 will be added between the 2 and 3. Let's think about it if we change the numbers you appended. It is a linked list before insertion. We may change 20,30,54,24 something like this. or we don't know the exact number but we know the node is not empty. In this case, we may add another instance that could be indexing the linked list. The "key" will be equal to the "index" of the linked list elements.
I hope this is clear the confusion.
Where are you?
Great video as it usually is!
By the way, how come you didn't put 'new_node.prev = cur' in the add_after function and 'new_node.prev = prev' in the add_before function?
Thanks!
Both of those functions have different purposes, and one of those variables make sense in one, but not the other.
@@LucidProgramming thank you for your teaching!
@@lunghunglin5729 No problem, thanks for your kind comments!
In the methods/functions 'add_after_node' and 'add_before_node' there should be return in the elif right ? Otherwise we may be traversing the doubly linked list for no reason even after adding the new node
Hi Vidya. I don't think so. The first "if" statement should catch these conditions, right? Might be misunderstanding what you're suggesting.
@@LucidProgramming Hi - These are excellent tutorials and I used them - to code along and to learn about doubly linked list. However learning means - I have print statements everywhere to understand. What I notice is that after adding a node - using either 'add_before_node' or 'add_after_node' - the while loop still loops through the entire linked list which I presume one does not want. Check it out - add two nodes with same data - and use one of the methods. You will notice that it will add the node twice. However I think after adding the first time it should exit out of the loop.
@@VidyaBhandary Oh okay, thanks for providing more information on this. I think I see what you're saying, and yes, you could have an early exit condition to prevent from needlessly traversing the list. Thanks for pointing that out!
Awesome! I haven't look the video so not sure if you explained correctly but missed in the solution. After adding a node the list is no more remain a double linked list as you missed attaching previous of newly added node. To fix in case of add_after_node, add new_node.prev = cur after new_node.next = nxt.
Hi aroradev. Thanks! I'm not sure I understand your comment.
Just an observation -- If key is repeated in the data,the new element is added before/after every occurance of the key instead of just the first occurance. DL = 1,2,1,2 and new_elem = 9; output = 1,9,2,1,9,2.
i don't know if u intended to do that..
Anyways great videos..Lots of Thanks..
Yep, I believe that was the intention. Sorry if it wasn't properly conveyed :P
Nice video 😁
Thank you! :)
when I am trying to insert at the end of list it gives me Error AttributeError: 'NoneType' object has no attribute 'prev'
Might want to double-check your code against the one in the video. Cheers!
Why did you miss writing "new_node.prev = cur" in your GitHub for the add_after_node() and "new_node.prev = prev" in the add_before_node()?
Thanks for pointing that out, Twisha, and thanks for watching! :)
Can You Please create a Playlist of Every video you created for Python Data structure?
Done! bit.ly/lp_data_structures
Is this code okay ?:
def middle(self,index,data):
n = input("Do you wish to add a node before the head (Y/N) ")
if n == "Y":
print("Then use the prepend function ")
newnode = Node(data)
cur = self.head
count = 0
while cur:
prev = cur
cur = cur.next
if count == index:
prev.next = newnode
newnode.prev = prev
newnode.next = cur
cur.prev = newnode
return
count+=1
I think the first "if" statement you have in the function is a bit oddly placed.
@@LucidProgramming The code seems to work fine, should i remove that condition ?
@@akashvenugopal2489 The "if" statement won't effect the output, but it's just a weird thing to ask the user in that place that you're asking it. The flow there just seems strange to me.
@@LucidProgramming Yeah you are right, i should remove it
In github code -->> add_before_node method -->> new_node.prev is not assigned.
Hmm, not sure what line you're referring to or what part of the code etc.
Alternate implementation for after node, before a node can be implemented in the same way.
class Node:
def __init__(self,data):
self.data = data
self.prev = None
self.next = None
class DoublyLinkedList:
def __init__(self):
self.head = None
def append(self,data):
#Check if list is empty or not
new_node = Node(data)
if self.head is None:
self.head = new_node
return
#Loop though the list and find the last node
curr = self.head
while curr.next:
curr = curr.next
curr.next = new_node
def print_list(self):
curr = self.head
while curr:
print(curr.data)
curr = curr.next
def after_node(self,after,data):
new_node = Node(data)
#If list is empty
if self.head is None:
self.head = new_node
else:
curr_node = self.head
while not curr_node.next is None and curr_node.data != after:
curr_node = curr_node.next
#Check if search node is present or not
if curr_node.data != after:
print(f'{after} node is not present in the list')
else:
#Check if it is the last node
if curr_node.next is None:
curr_node.next = new_node
new_node.prev = curr_node
else:
next_node = curr_node.next
curr_node.next = new_node
new_node.next = next_node
new_node.prev = curr_node
new_node.prev = new_node
l_list = DoublyLinkedList()
l_list.append('A')
l_list.append('B')
l_list.append('C')
l_list.append('D')
l_list.after_node('C','Insert this')
l_list.print_list()
Thanks for sharing!
Thank you 👌
def print_links(self):
if not self.head:
return "Linked List is Empty"
else:
return self.__print_helper_links(self.head)
def __print_helper_links(self, head):
# Base Case:
if not head.next:
return F"({str(head.data)})" + F" Previous: {head.previous.data} |" \
F" Next: {head.next.dataif head.next else head.next}"
else:
return F"({str(head.data)})" +\
F" Previous: {head.previous.data if head.previous else head.previous } |" \
F" Next: {head.next.data} " +\
" " + self.__print_helper_links(head.next)
I implemented this additional function within the Doubly-Linked List class, this way I have easier time seeing all values, their previous values (if any) and next values (if any).
Thought of sharing it with you guys.
sorry how self.data == key I think is wrong it's not logic we must change self.data with traversing until with the index if we changing instances with other values the insert after node doesn't work but instead of video is good and so simply
Hmm. Not sure I understand. Can you give an explicit counterexample with code?
@@LucidProgramming
def traverseToIndex(self, index):
self.counter = 0
self.currentNode = self.head
while self.counter != index :
self.currentNode = self.currentNode.next
self.counter +=1
return self.currentNode
@@mohamedkhaled-qc7kb Is this the code that generates the error or the proposed fix? I'm confused here. Sorry.
@@LucidProgramming excuse me in video you self.data == key that does not sense because how data or input equal the key or index ???
@@mohamedkhaled-qc7kb But the key is the thing that we are looking for.