Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions Sprint-2/implement_linked_list/linked_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#node class to hold value and pointer
class Node:
def __init__(self,data):
self.data = data
self.next = None # pointer to next node
self.prev = None # pointer to previous node
Comment on lines +1 to +6

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

  • Common practice is to keep a spacing between parameters. Prettier does not support Python, you would probably need to install a different formatter for Python.

  • Could consider using docstrings instead of comments do document a class/function.

  • May I suggest exploring the use of __slots__ to reduce memory usage?


#LinkedList class to manage chain of nodes

class LinkedList:
def __init__(self):
self.head = None # pointer to head
self.tail = None # pointer to tail

#insert at the beginning

def push_head(self,data):
new_node = Node(data)

if not self.head: #if the node is empty it will have both head & tail

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

  • The condition could also evaluate to True if self.head is False. Could you look up a more suitable and preferred syntax to check if a value is None?

  • A small suggestion: try to avoid comments that simply restate what the code already makes clear. In this case, the code is self-explanatory, so the comment doesn't really add any new information. Comments are most useful when they explain why something is done, clarify non-obvious behaviour, or document an important assumption. This helps keep the code clean and makes the comments that we do have more valuable.

self.head = new_node
self.tail = new_node
else:
new_node.next = self.head # pointer to next new node
self.head.prev = new_node # pointer back to old node by new node
self.head = new_node # move head pointer to new_node

return new_node

#remove data from last node & show the value
def pop_tail(self):
if not self.tail: #if list is empty nothing to pop
return None
tail_node = self.tail
removed_data = tail_node.data # save value to return later

if self.head == self.tail:
self.head = None
self.tail = None
else:
self.tail = self.tail.prev
self.tail.next = None
Comment on lines +37 to +42

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Could consider delegating the node removing task to remove() -- less code to maintain.


return removed_data

#remove specific node

def remove(self,node):

#do list is empty
if not self.head:
return

# if node is head move head to next node
if node == self.head:
self.head = node.next

#if node is tail move tail to prev node
if node == self.tail:
self.tail = node.prev

#unlink node from its neighbors
# check is there a node before
if node.prev:
node.prev.next = node.next
#check is there a node after
if node.next:
node.next.prev = node.prev

# clean up pointers on the removed node

node.prev = None
node.next = None






Loading