Skip to content

Update doubly_linked_list.py #2573

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 12 commits into from
154 changes: 121 additions & 33 deletions data_structures/linked_list/doubly_linked_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@


class Node:
def __init__(self, data, previous=None, next=None):
def __init__(self, data, previous=None, next_node=None):
self.data = data
self.previous = previous
self.next = next
self.next = next_node

def __str__(self):
return f"{self.data}"
Expand All @@ -33,6 +33,24 @@ def __str__(self):
current = current.next
return "<-->".join(str(node) for node in nodes)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find the "<—>" notation to be a lot of visual clutter. Why not just add an .__iter__() method and then return str(list(self))?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi sir,
I have added in a linked list iterator class for iterating over the linked list
and removed the <--> representation.

However, I have left the str(self) same and just removed the <--> from the string as
this would keep visualizing the linked list if someone wants to visualize the data in the Linked list while debugging as opposed to the memory address that it spits out

I had previously used the <--> representation as I thought it would make the links between nodes more clear

@cclauss I have made the changes


def __contains__(self, value):
current = self.head
while current:
if current.data == value:
return True
current = current.next
return False

def get_head_data(self):
if self.head:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if self.head:
return self.head.data if self.head else None

Same with get_tail_data()

return self.head.data
return None

def get_tail_data(self):
if self.tail:
return self.tail.data
return None

def set_head(self, node: Node) -> None:

if self.head is None:
Expand Down Expand Up @@ -107,6 +125,8 @@ def delete_value(self, value):
self.tail = self.tail.previous

self.remove_node_pointers(node)
else:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function signature does not say that this function returns a string. My sense is that we should raise an exception.

return 'Node not found'

@staticmethod
def remove_node_pointers(node: Node) -> None:
Expand All @@ -123,35 +143,103 @@ def is_empty(self):
return self.head is None


linked_list = LinkedList()
for i in range(10):
linked_list.insert(i)

print(linked_list)
# 0<-->1<-->2<-->3<-->4<-->5<-->6<-->7<-->8<-->9
print(linked_list.head)
# 0
linked_list.delete_value(0)
print(linked_list.head)
# 1
print(linked_list)
# 1<-->2<-->3<-->4<-->5<-->6<-->7<-->8<-->9
linked_list.insert_at_position(1, 100)
# 100<-->1<-->2<-->3<-->4<-->5<-->6<-->7<-->8<-->9
print(linked_list)
linked_list.delete_value(5)
print(linked_list)
# 100<-->1<-->2<-->3<-->4<-->6<-->7<-->8<-->9
print(linked_list.is_empty())
# False
linked_list.insert_at_position(12, 200)

for i in range(5):
def create_linked_list():
"""
>>> new_linked_list = LinkedList()
>>> new_linked_list.get_head_data() is None
True

>>> new_linked_list.get_tail_data() is None
True

>>> new_linked_list.is_empty()
True

>>> new_linked_list.insert(10)
>>> new_linked_list.get_head_data()
10

>>> new_linked_list.get_tail_data()
10

>>> new_linked_list.insert_at_position(position=3, value=20)
>>> new_linked_list.get_head_data()
10

>>> new_linked_list.get_tail_data()
20

>>> new_linked_list.set_head(Node(1000))
>>> new_linked_list.get_head_data()
1000

>>> new_linked_list.get_tail_data()
20

>>> new_linked_list.set_tail(Node(2000))
>>> new_linked_list.get_head_data()
1000
>>> new_linked_list.get_tail_data()
2000

>>> new_linked_list.is_empty()
False

>>> 10 in new_linked_list
True

>>> new_linked_list.delete_value(value=10)
>>> 10 in new_linked_list
False

>>> new_linked_list.delete_value(value=5000)
'Node not found'

>>> new_linked_list.delete_value(value=2000)
>>> new_linked_list.get_tail_data()
20

>>> new_linked_list.delete_value(value=1000)
>>> new_linked_list.get_tail_data()
20
>>> new_linked_list.get_head_data()
20
"""
linked_list = LinkedList()
for i in range(10):
linked_list.insert(value=i)

print(linked_list)
# 0<-->1<-->2<-->3<-->4<-->5<-->6<-->7<-->8<-->9
print(linked_list.head)
# 0
linked_list.delete_value(value=0)
print(linked_list.head)
# 1
print(linked_list)
# 1<-->2<-->3<-->4<-->5<-->6<-->7<-->8<-->9
linked_list.insert_at_position(position=1, value=100)
# 100<-->1<-->2<-->3<-->4<-->5<-->6<-->7<-->8<-->9
print(linked_list)
linked_list.delete_value(value=5)
print(linked_list)
linked_list.delete_value(linked_list.tail.data)
# for each iterations
# 100 < -->1 < -->2 < -->3 < -->4 < -->6 < -->7 < -->8 < -->9 < -->200
# 100 < -->1 < -->2 < -->3 < -->4 < -->6 < -->7 < -->8 < -->9
# 100 < -->1 < -->2 < -->3 < -->4 < -->6 < -->7 < -->8
# 100 < -->1 < -->2 < -->3 < -->4 < -->6 < -->7
# 100 < -->1 < -->2 < -->3 < -->4 < -->6
# 100<-->1<-->2<-->3<-->4<-->6<-->7<-->8<-->9
print(linked_list.is_empty())
# False
linked_list.insert_at_position(position=12, value=200)

for i in range(5):
print(linked_list)
linked_list.delete_value(linked_list.tail.data)
# for each iterations
# 100 < -->1 < -->2 < -->3 < -->4 < -->6 < -->7 < -->8 < -->9 < -->200
# 100 < -->1 < -->2 < -->3 < -->4 < -->6 < -->7 < -->8 < -->9
# 100 < -->1 < -->2 < -->3 < -->4 < -->6 < -->7 < -->8
# 100 < -->1 < -->2 < -->3 < -->4 < -->6 < -->7
# 100 < -->1 < -->2 < -->3 < -->4 < -->6


if __name__ == '__main__':
import doctest

doctest.testmod()