Skip to content

West Midlands | 26 March SDC | Iswat Bello | Sprint 2 | Implement a linked list in python#191

Open
Iswanna wants to merge 12 commits into
CodeYourFuture:mainfrom
Iswanna:implement-a-linked-list-in-python
Open

West Midlands | 26 March SDC | Iswat Bello | Sprint 2 | Implement a linked list in python#191
Iswanna wants to merge 12 commits into
CodeYourFuture:mainfrom
Iswanna:implement-a-linked-list-in-python

Conversation

@Iswanna

@Iswanna Iswanna commented Jun 30, 2026

Copy link
Copy Markdown

Learners, PR Template

Self checklist

  • I have titled my PR with Region | Cohort | FirstName LastName | Sprint | Assignment Title
  • My changes meet the requirements of the task
  • I have tested my changes
  • My changes follow the style guide

Changelist

In this PR, I implemented a Doubly Linked List to handle data storage and removal efficiently. A detailed breakdown of the implementation and trade-offs can be found in the CHANGES-MADE.md file included in this submission.

Key Changes

  • Node & LinkedList Classes: Defined a Node class with bidirectional pointers (next and previous) and a LinkedList class to manage the head and tail.
  • Method Implementation:
    • push_head(value): Adds a node to the front in O(1) time.
    • pop_tail(): Removes the last node in O(1) time, including logic to handle single-node and empty lists.
    • remove(node): A robust method that re-links neighboring nodes to remove a specific entry from anywhere in the list.
  • Pointer Management: Ensured that all pointers (head, tail, next, and previous) are correctly updated during every operation to maintain list integrity.

Testing Done

I verified the code using unittest with the following scenarios:

  • Standard push_head and pop_tail sequences.
  • Middle Removal: Verified that removing a center node correctly re-wires the nodes ahead and behind it.
  • Empty List Handling: Confirmed that pop_tail returns None rather than crashing when the list is empty.
  • Null Safety: Confirmed that remove(None) is handled gracefully.

Learning Reflection (Trade-offs)

I applied a space-vs-time trade-off by using extra memory (for the previous pointer) to ensure that adding to the head and removing from the tail stays at O(1) speed regardless of how many items are in the list.

Iswanna added 8 commits June 30, 2026 12:56
- Define Node class to store value
- Add pointers for next and previous nodes
- Define the LinkedList class in linked_list.py.
- Implement the __init__ method to track the head and tail of the list.
- Initialize head and tail to None for an empty list state.
- Added the logic to create a new node and insert it at the front of the list.

- Handled pointer updates for both empty and non-empty list states.

- Returns the new node to allow for future removal/referencing.
- Added logic to remove the last node from the list.
- Handles edge cases for empty lists and single-node lists.
- Updates tail pointers and returns the value of the removed node.
- Added logic to remove a specific node from any position.
- Included pointer updates for head and tail edge cases.
- Added neighbor re-linking to maintain list integrity.
- Added test_remove_middle to verify pointer re-linking when deleting from the center.
- Added test_pop_empty_list to ensure the program doesn't crash on empty lists.
- Added test_remove_none to verify handling of null input.
- Documented core logic for Node and LinkedList classes
- Explained testing strategy for edge cases (empty lists, middle removal)
- Traded extra memory space to achieve O(1) time (constant speed).
- Changed "Linked List" to "Doubly Linked List" to accurately reflect the bi-directional implementation.
- Updated header for better technical clarity.
@github-actions

This comment has been minimized.

1 similar comment
@github-actions

This comment has been minimized.

@Iswanna Iswanna added 📅 Sprint 2 Assigned during Sprint 2 of this module Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. Module-Complexity The name of the module. labels Jun 30, 2026
@github-actions

This comment has been minimized.

@github-actions github-actions Bot removed the Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. label Jun 30, 2026
@github-actions

This comment has been minimized.

1 similar comment
@github-actions

This comment has been minimized.

@Iswanna Iswanna changed the title West Midlands | 26 March SDC | Iswat Bello | Sprint 1 | Implement a linked list in python West Midlands | 26 March SDC | Iswat Bello | Sprint 2 | Implement a linked list in python Jun 30, 2026
@Iswanna Iswanna added the Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. label Jul 2, 2026
Comment on lines +2 to +9
"""
Represents a single person in line.
Stores a value and links to the people ahead and behind.
"""
def __init__(self, value):
self.value = value
self.next = None # The person ahead
self.previous = None # The person behind

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thank you for the suggestion. I have implemented __slots__ to reduce memory usage.

Comment on lines +28 to +32
# Logic 3: If the list is not empty
else:
new_node.next = self.head # New person grabs old head's hand
self.head.previous = new_node # Old head reaches back to new person
self.head = new_node # New person is now the head

@cjyuan cjyuan Jul 2, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

  • else already means "opposite", so you could probably drop the comment on line 28.

  • The comments on line 30-32 actually confuses me because it refers to "person". Are they your own notes? If so, it might not be a good idea to leave them in "production" code.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thank you for the feedback.
Those metaphors were part of my initial notes to help me understand the concept. I've cleaned up the code to remove the non-technical language and the redundant logic labels.

Comment on lines +19 to +20

def push_head(self, value):

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 adding type hints to each method to clearly specify the types of its parameters and return value.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thank you for the feedback. I have updated the code to implement your suggestions.

Comment on lines +46 to +53
# Logic 2: If there is only one person in line
if self.head == self.tail:
self.head = None
self.tail = None
# Logic 3: If there are more people
else:
self.tail = self.tail.previous # Move tail back one
self.tail.next = None # New tail lets go of the old 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.

Why not just call remove()?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thank you for the suggestion. I’ve refactored the pop_tail method to call self.remove(self.tail)

Comment on lines +43 to +44
# Logic 1: Store the value to return later
value_to_return = self.tail.value

@cjyuan cjyuan Jul 2, 2026

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 variable name is self-explanatory. The comment does not provide any more info.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I have removed all redundant comments. Thank you.

Comment on lines +46 to +50
# Logic 2: If there is only one person in line
if self.head == self.tail:
self.head = None
self.tail = None
# Logic 3: If there are more people

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What do these "logic numbers" represent?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

They represented the steps of the logic, but I have now removed them.

@cjyuan cjyuan added Reviewed Volunteer to add when completing a review with trainee action still to take. and removed Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. labels Jul 2, 2026
Iswanna added 4 commits July 3, 2026 11:50
- Add __slots__ to prevent per-instance dictionary overhead
- Optimize space complexity for large-scale list usage
- Remove numbered logic comments (# Logic 1, 2, 3) to reduce noise
- Remove non-technical metaphors (e.g., "New person") in favor of self-documenting code
- Clean up method bodies to follow professional clean code standards
- Implement typing (Any, Optional) for parameters and return values
- Add forward references for Node pointers
- Replace manual pointer logic in pop_tail with a call to self.remove()
- Adhere to DRY (Don't Repeat Yourself) principles
- Reduce code duplication and improve maintainability
@Iswanna Iswanna added Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. and removed Reviewed Volunteer to add when completing a review with trainee action still to take. labels Jul 3, 2026
@Iswanna Iswanna requested a review from cjyuan July 3, 2026 11:26

@cjyuan cjyuan left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Changes look great. Code is very clean!

If you want to enforce that a linked list can only contain values of a single type (e.g. all ints or all strs), have a look at Python's TypeVar and Generic type hints. They're commonly used to make data structures type-safe while remaining reusable.

@cjyuan cjyuan added Complete Volunteer to add when work is complete and all review comments have been addressed. and removed Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. labels Jul 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Complete Volunteer to add when work is complete and all review comments have been addressed. Module-Complexity The name of the module. 📅 Sprint 2 Assigned during Sprint 2 of this module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants