Skip to content

West Midlands | 26 March SDC | Iswat Bello | Sprint 2 | Implement an LRU cache in python#193

Open
Iswanna wants to merge 10 commits into
CodeYourFuture:mainfrom
Iswanna:implement-an-LRU-cache-in-python
Open

West Midlands | 26 March SDC | Iswat Bello | Sprint 2 | Implement an LRU cache in python#193
Iswanna wants to merge 10 commits into
CodeYourFuture:mainfrom
Iswanna:implement-an-LRU-cache-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 have implemented a standalone LRU (Least Recently Used) Cache. This task required building a purpose-built Doubly Linked List and Dictionary hybrid to ensure O(1) worst-case time complexity for both get and set operations.

A detailed explanation of the architecture and the logic behind the pointer management is available in the CHANGES_MADE.md file.

Key Features

  • Standalone Implementation: Developed a custom Node and LinkedList class specifically for the requirements of an LRU Cache, separate from previous tasks.
  • Bidirectional Nodes: Designed the Node class to store both keys and values. This enables the "reverse lookup" required to synchronize the dictionary when a node is evicted from the tail of the list.
  • O(1) Efficiency: By combining a dictionary for instant lookups and a linked list for instant ordering, the cache remains performant regardless of its size.
  • Eviction Logic: Automatically removes the least recently used item when the specified limit is reached.

Testing Done

Verified the implementation with unittest in lru_cache_test.py, including:

  • Standard set/get sequences and limit enforcement.
  • MRU Refreshing: Ensuring get operations move items to the front of the list.
  • Edge Case - Limit 1: Confirmed correct behavior for the smallest possible cache.
  • Update Logic: Verified that overwriting an existing key updates the value and refreshes its position without increasing cache size.
  • Null Safety: Handled non-existent keys and null inputs gracefully.

Learning Reflection

This implementation demonstrates the Space-vs-Time trade-off. By using extra memory for a dictionary and a bidirectional linked list, I ensured that the speed of the system is not sacrificed as the data set grows.

Iswanna added 10 commits June 30, 2026 14:25
- Add 'key' attribute to Node to facilitate dictionary cleanup during eviction
- Maintain pointers for doubly linked list functionality
- Initialize head and tail pointers for the Doubly Linked List
- Add documentation explaining MRU (head) and LRU (tail) logic
- Add logic to insert nodes at the front of the list (Most Recently Used)
- Ensure tail pointer is set correctly when adding to an empty list
- Update previous/next pointers of existing head to maintain bi-directional links
- Add logic to remove and return the least recently used (tail) node
- Handle single-node list resets by clearing both head and tail pointers
- Ensure the new tail's 'next' pointer is cleared to prevent memory leaks
- Add logic to disconnect a node from any position in the list
- Update head and tail pointers when removing boundary nodes
- Nullify removed node pointers to ensure a clean disconnection
- Add constructor with validation to ensure limit is at least 1
- Initialize dictionary for O(1) key-to-node lookups
- Initialize LinkedList to track item access order
- Add O(1) lookup functionality using the dictionary
- Implement move-to-front logic to mark accessed items as Most Recently Used
- Return None for keys not present in the cache
- Add logic to update existing keys and move them to the front (MRU)
- Implement eviction of the Least Recently Used (tail) node when the limit is reached
- Ensure the lookup dictionary and linked list stay synchronized during eviction
- Add new nodes to both the dictionary and the front of the list
- Verify that updating existing keys correctly refreshes their MRU status
- Test edge case for a cache with a limit of one
- Add test for retrieving non-existent keys (returning None)
- Confirm support for complex data types like lists and dictionaries
- Explain hybrid architecture (Dictionary + Doubly Linked List)
- Document the "why" behind O(1) time complexity requirements
- Detail the space-vs-time trade-off used in the design
- Summarize testing strategy for edge cases and eviction logic
@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
@Iswanna Iswanna changed the title West Midlands | 26 March SDC | Iswat Bello | Sprint 1 | Implement an LRU cache in python West Midlands | 26 March SDC | Iswat Bello | Sprint 2 | Implement an LRU cache 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

@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.

Looks good.

Comment on lines +7 to +11
def __init__(self, key, value):
self.key = key
self.value = value
self.next = None
self.previous = None

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

To practice code reuse, you could import the linked list you implemented in the other exercise and store the key-value pairs as a tuple in each node.

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.

By storing the key and value together as a tuple inside the node, I could use the Linked List I already built without having to write a new one for this file. Thanks for the suggestion.

@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 2, 2026
@Iswanna

Iswanna commented Jul 4, 2026

Copy link
Copy Markdown
Author

Looks good.

Thank you for the feedback.

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