33![ CI] ( https://github.com/azizjon-aliev/python-dsa/actions/workflows/ci.yml/badge.svg )
44![ Coverage] ( https://img.shields.io/badge/coverage-97%25-brightgreen )
55![ Python] ( https://img.shields.io/badge/python-3.13%2B-blue )
6+ ![ License] ( https://img.shields.io/badge/license-MIT-green )
67
7- A collection of classic data structures and algorithms implemented in Python.
8+ Classic data structures and algorithms implemented from scratch in pure Python for learning purposes. Every implementation includes full type hints, ABC interfaces, ` __repr__ ` / ` __str__ ` / ` __eq__ ` / ` __bool__ ` support, and comprehensive tests .
89
9- ## Data Structures
10+ ## Table of Contents
1011
11- ### Stacks
12+ - [ Data Structures] ( #data-structures )
13+ - [ Arrays] ( #arrays )
14+ - [ Linked Lists] ( #linked-lists )
15+ - [ Stacks] ( #stacks )
16+ - [ Algorithms] ( #algorithms )
17+ - [ Searching] ( #searching )
18+ - [ Getting Started] ( #getting-started )
19+ - [ Testing] ( #testing )
20+ - [ Project Structure] ( #project-structure )
21+ - [ Contributing] ( #contributing )
22+ - [ License] ( #license )
1223
13- | Implementation | Description |
14- | ---| ---|
15- | ` ArrayStack ` | Stack backed by a ` DynamicArray ` . O(1) amortised push/pop/peek. |
16- | ` LinkedListStack ` | Stack backed by a ` SinglyLinkedList ` . O(1) worst-case push/pop/peek. |
17- | ` MinStack ` | Extends ` ArrayStack ` with O(1) ` get_min() ` tracking via an auxiliary stack. |
24+ ## Data Structures
1825
19- ``` python
20- from data_structures.stack.array_stack import ArrayStack
21- from data_structures.stack.linked_list_stack import LinkedListStack
22- from data_structures.stack.min_stack import MinStack
26+ All structures implement common Python protocols: ` len() ` , ` in ` , ` bool() ` , ` == ` , ` repr() ` , ` str() ` , iteration.
2327
24- s = ArrayStack() # or LinkedListStack()
25- s.push(1 )
26- s.push(2 )
27- s.peek() # 2
28- s.pop() # 2
29- s.size() # 1
30- repr (s) # "ArrayStack([1])"
31- str (s) # "1"
28+ ### Arrays
3229
33- ms = MinStack()
34- ms.push(5 )
35- ms.push(3 )
36- ms.push(7 )
37- ms.get_min() # 3
38- ```
30+ | Implementation | Description | Access | Append | Insert/Remove |
31+ | ---| ---| ---| ---| ---|
32+ | ` StaticArray ` | Fixed-capacity array | O(1) | O(1) | O(n) |
33+ | ` DynamicArray ` | Auto-resizing array (2x growth, 1/4 shrink) | O(1) | O(1)* | O(n) |
3934
40- ### Arrays
35+ \* amortised
4136
42- | Implementation | Description |
43- | ---| ---|
44- | ` StaticArray ` | Fixed-capacity array. O(1) access, O(n) insert/remove. Raises ` OverflowError ` when full. |
45- | ` DynamicArray ` | Resizable array that doubles on overflow and halves when sparse. O(1) amortised append/pop. |
37+ ** Features:** negative indexing, slicing (` arr[1:3] ` , ` arr[::-1] ` ), construction from iterables.
4638
4739``` python
4840from data_structures.array.static_array import StaticArray
4941from data_structures.array.dynamic_array import DynamicArray
5042
51- sa = StaticArray([1 , 2 , 3 ]) # or StaticArray(3) for empty
52- repr (sa) # "StaticArray([1, 2, 3])"
53- str (sa) # "[1, 2, 3]"
54- list (sa) # [1, 2, 3]
55- sa.pop() # 3
56- sa.insert(0 , 0 )
57- sa.remove(1 ) # 1
43+ # Static array — fixed capacity
44+ sa = StaticArray([1 , 2 , 3 ])
45+ sa[0 ] # 1
46+ sa[- 1 ] # 3
47+ sa[::2 ] # [1, 3]
5848
59- da = DynamicArray([1 , 2 , 3 ]) # or DynamicArray() for empty
60- for i in range (4 , 11 ):
49+ # Dynamic array — grows and shrinks automatically
50+ da = DynamicArray()
51+ for i in range (1 , 6 ):
6152 da.append(i)
62- len (da) # 10
63- da.pop() # 10
64- da.capacity # 16
53+ str (da) # "[1, 2, 3, 4, 5]"
54+ da[:: - 1 ] # [5, 4, 3, 2, 1]
55+ da == StaticArray([ 1 , 2 , 3 , 4 , 5 ]) # True (cross-type equality)
6556```
6657
6758### Linked Lists
6859
69- | Implementation | Description |
70- | ---| ---|
71- | ` SinglyLinkedList ` | Singly linked list with O(1) push/pop at the head. |
72- | ` DoublyLinkedList ` | Doubly linked list with O(1) push/pop at both head and tail. |
60+ | Implementation | Description | Push/Pop Front | Push/Pop Back |
61+ | ---| ---| ---| ---|
62+ | ` SinglyLinkedList ` | Forward-only traversal | O(1) | — |
63+ | ` DoublyLinkedList ` | Bidirectional traversal | O(1) | O(1) |
64+
65+ ** Features:** ` reversed() ` for DoublyLinkedList, cross-type equality, arrow-notation ` str() ` .
7366
7467``` python
7568from data_structures.linked_list import SinglyLinkedList, DoublyLinkedList
7669
7770sll = SinglyLinkedList()
7871sll.push_front(1 )
7972sll.push_front(2 )
80- sll.peek_front() # 2
81- str (sll) # "2 -> 1"
82- sll.pop_front() # 2
83- list (sll) # [1]
73+ str (sll) # "2 -> 1"
8474
8575dll = DoublyLinkedList()
86- dll.push_front (1 )
76+ dll.push_back (1 )
8777dll.push_back(2 )
8878dll.push_back(3 )
89- str (dll) # "1 <-> 2 <-> 3"
90- dll.peek_back() # 3
91- dll.pop_back() # 3
92- list (dll) # [1, 2]
79+ str (dll) # "1 <-> 2 <-> 3"
80+ list (reversed (dll)) # [3, 2, 1]
81+
82+ sll == dll # True (same elements in same order)
83+ ```
84+
85+ ### Stacks
86+
87+ | Implementation | Description | Push | Pop | Peek |
88+ | ---| ---| ---| ---| ---|
89+ | ` ArrayStack ` | Backed by ` DynamicArray ` | O(1)* | O(1)* | O(1) |
90+ | ` LinkedListStack ` | Backed by ` SinglyLinkedList ` | O(1) | O(1) | O(1) |
91+ | ` MinStack ` | ` ArrayStack ` + O(1) ` get_min() ` | O(1)* | O(1)* | O(1) |
92+
93+ \* amortised
94+
95+ ** Features:** cross-type equality, top-to-bottom ` str() ` display.
96+
97+ ``` python
98+ from data_structures.stack.array_stack import ArrayStack
99+ from data_structures.stack.linked_list_stack import LinkedListStack
100+ from data_structures.stack.min_stack import MinStack
101+
102+ s = ArrayStack()
103+ s.push(1 ); s.push(2 ); s.push(3 )
104+ str (s) # "3 -> 2 -> 1"
105+ s.peek() # 3
106+ s.pop() # 3
107+ bool (s) # True
108+
109+ ms = MinStack()
110+ for v in [5 , 3 , 7 , 1 ]:
111+ ms.push(v)
112+ ms.get_min() # 1
93113```
94114
95115## Algorithms
@@ -98,9 +118,11 @@ list(dll) # [1, 2]
98118
99119| Algorithm | Time | Space | Description |
100120| ---| ---| ---| ---|
101- | ` binary_search ` | O(log n) | O(1) | Find element index in sorted sequence, or -1. |
102- | ` lower_bound ` | O(log n) | O(1) | Index of first element >= target. |
103- | ` upper_bound ` | O(log n) | O(1) | Index of first element > target. |
121+ | ` binary_search ` | O(log n) | O(1) | Index of target in sorted sequence, or -1 |
122+ | ` lower_bound ` | O(log n) | O(1) | Index of first element >= target |
123+ | ` upper_bound ` | O(log n) | O(1) | Index of first element > target |
124+
125+ Works with any indexable collection (` list ` , ` StaticArray ` , ` DynamicArray ` ).
104126
105127``` python
106128from algorithms.searching.binary_search import binary_search, lower_bound, upper_bound
@@ -110,73 +132,71 @@ binary_search([1, 3, 5, 7, 9], 4) # -1
110132
111133lower_bound([1 , 3 , 3 , 3 , 5 ], 3 ) # 1 (first >= 3)
112134upper_bound([1 , 3 , 3 , 3 , 5 ], 3 ) # 4 (first > 3)
113-
114- # Works with StaticArray and DynamicArray too
115- binary_search(StaticArray([1 , 2 , 3 ]), 2 ) # 1
116- binary_search(DynamicArray([1 , 2 , 3 ]), 2 ) # 1
117135```
118136
119- ## Requirements
120-
121- - Python >= 3.13
122- - [ uv] ( https://docs.astral.sh/uv/ ) (package manager)
123- - [ ruff] ( https://docs.astral.sh/ruff/ ) (linter & formatter)
124- - [ ty] ( https://docs.astral.sh/ty/ ) (type checker)
125- - [ pre-commit] ( https://pre-commit.com/ ) (git hooks)
126-
127137## Getting Started
128138
139+ ** Requirements:** Python >= 3.13, [ uv] ( https://docs.astral.sh/uv/ )
140+
129141``` bash
130- # Install dependencies
142+ git clone https://github.com/azizjon-aliev/python-dsa.git
143+ cd python-dsa
131144uv sync --group dev
145+ uv run pre-commit install
146+ ```
147+
148+ ## Testing
132149
133- # Run tests (with coverage)
150+ ``` bash
151+ # Unit tests with coverage (248 tests, 97% coverage)
134152uv run pytest tests/ -v
135153
136- # Run benchmarks
154+ # Property-based tests (hypothesis)
155+ uv run pytest tests/test_properties.py -v
156+
157+ # Benchmarks
137158uv run pytest tests/test_benchmarks.py --benchmark-enable --no-cov
138159
139- # Run doctests
160+ # Doctests
140161uv run pytest --doctest-modules data_structures/ algorithms/ --no-cov
141162
142- # Lint & format
143- uv run ruff check .
144- uv run ruff format .
145-
146- # Type check
147- uv run ty check
148-
149- # Run all pre-commit hooks
150- uv run pre-commit run --all-files
163+ # Lint, format, type check
164+ uv run ruff check . && uv run ruff format --check . && uv run ty check
151165```
152166
153167## Project Structure
154168
155169```
156170data_structures/
157171 array/
158- base.py # IArray ABC
159- static_array.py # StaticArray implementation
160- dynamic_array.py # DynamicArray implementation
172+ base.py # IArray ABC
173+ static_array.py # StaticArray
174+ dynamic_array.py # DynamicArray
161175 stack/
162- base.py # IStack ABC and StackEmptyError
163- array_stack.py # ArrayStack implementation
164- linked_list_stack.py # LinkedListStack implementation
165- min_stack.py # MinStack implementation
176+ base.py # IStack ABC, StackEmptyError
177+ array_stack.py # ArrayStack
178+ linked_list_stack.py # LinkedListStack
179+ min_stack.py # MinStack
166180 linked_list/
167- base.py # ISinglyLinkedList & IDoublyLinkedList ABCs
168- singly_linked_list.py # SinglyLinkedList
169- doubly_linked_list.py # DoublyLinkedList
181+ base.py # ISinglyLinkedList, IDoublyLinkedList ABCs
182+ singly_linked_list.py
183+ doubly_linked_list.py
170184algorithms/
171185 searching/
172- binary_search.py # binary_search, lower_bound, upper_bound
186+ binary_search.py # binary_search, lower_bound, upper_bound
173187tests/
174- test_arrays.py # pytest suite for array implementations
175- test_stacks.py # pytest suite for stack implementations
176- test_linked_lists.py # pytest suite for linked list implementations
177- test_binary_search.py # pytest suite for binary search
178- test_benchmarks.py # pytest-benchmark performance tests
179- test_properties.py # hypothesis property-based tests
180- .pre-commit-config.yaml # pre-commit hooks (ruff, ty)
181- pyproject.toml # project config, tools settings
188+ test_arrays.py # Array unit tests
189+ test_stacks.py # Stack unit tests
190+ test_linked_lists.py # Linked list unit tests
191+ test_binary_search.py # Binary search unit tests
192+ test_benchmarks.py # Performance benchmarks (pytest-benchmark)
193+ test_properties.py # Property-based tests (hypothesis)
182194```
195+
196+ ## Contributing
197+
198+ See [ CONTRIBUTING.md] ( CONTRIBUTING.md ) for guidelines.
199+
200+ ## License
201+
202+ [ MIT] ( LICENSE )
0 commit comments