Skip to content

Commit ace3204

Browse files
committed
Fix bubble sort logic and add comments
1 parent 3c88735 commit ace3204

File tree

1 file changed

+60
-123
lines changed

1 file changed

+60
-123
lines changed

sorts/bubble_sort.py

Lines changed: 60 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,132 +1,69 @@
1-
from typing import Any
2-
3-
4-
def bubble_sort_iterative(collection: list[Any]) -> list[Any]:
5-
"""Pure implementation of bubble sort algorithm in Python
6-
7-
:param collection: some mutable ordered collection with heterogeneous
8-
comparable items inside
9-
:return: the same collection ordered by ascending
10-
11-
Examples:
12-
>>> bubble_sort_iterative([0, 5, 2, 3, 2])
13-
[0, 2, 2, 3, 5]
14-
>>> bubble_sort_iterative([])
15-
[]
16-
>>> bubble_sort_iterative([-2, -45, -5])
17-
[-45, -5, -2]
18-
>>> bubble_sort_iterative([-23, 0, 6, -4, 34])
19-
[-23, -4, 0, 6, 34]
20-
>>> bubble_sort_iterative([0, 5, 2, 3, 2]) == sorted([0, 5, 2, 3, 2])
21-
True
22-
>>> bubble_sort_iterative([]) == sorted([])
23-
True
24-
>>> bubble_sort_iterative([-2, -45, -5]) == sorted([-2, -45, -5])
25-
True
26-
>>> bubble_sort_iterative([-23, 0, 6, -4, 34]) == sorted([-23, 0, 6, -4, 34])
27-
True
28-
>>> bubble_sort_iterative(['d', 'a', 'b', 'e']) == sorted(['d', 'a', 'b', 'e'])
29-
True
30-
>>> bubble_sort_iterative(['z', 'a', 'y', 'b', 'x', 'c'])
31-
['a', 'b', 'c', 'x', 'y', 'z']
32-
>>> bubble_sort_iterative([1.1, 3.3, 5.5, 7.7, 2.2, 4.4, 6.6])
33-
[1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7]
34-
>>> bubble_sort_iterative([1, 3.3, 5, 7.7, 2, 4.4, 6])
35-
[1, 2, 3.3, 4.4, 5, 6, 7.7]
36-
>>> import random
37-
>>> collection_arg = random.sample(range(-50, 50), 100)
38-
>>> bubble_sort_iterative(collection_arg) == sorted(collection_arg)
39-
True
40-
>>> import string
41-
>>> collection_arg = random.choices(string.ascii_letters + string.digits, k=100)
42-
>>> bubble_sort_iterative(collection_arg) == sorted(collection_arg)
43-
True
1+
from typing import Any, List
2+
3+
"""
4+
Bubble Sort Algorithms
5+
6+
This module provides iterative and optimized implementations
7+
of the Bubble Sort algorithm.
8+
9+
Time Complexity:
10+
Best Case: O(n)
11+
Average Case: O(n^2)
12+
Worst Case: O(n^2)
13+
14+
Space Complexity:
15+
O(1)
16+
"""
17+
18+
19+
def bubble_sort_iterative(collection: List[Any]) -> List[Any]:
4420
"""
45-
length = len(collection)
46-
for i in reversed(range(length)):
21+
Bubble Sort (Iterative)
22+
23+
Sorts a list in ascending order using the bubble sort algorithm.
24+
25+
:param collection: A mutable list of comparable elements
26+
:return: Sorted list
27+
"""
28+
29+
n = len(collection)
30+
if n < 2:
31+
return collection
32+
33+
for i in range(n):
4734
swapped = False
48-
for j in range(i):
35+
for j in range(0, n - i - 1):
4936
if collection[j] > collection[j + 1]:
50-
swapped = True
5137
collection[j], collection[j + 1] = collection[j + 1], collection[j]
38+
swapped = True
39+
5240
if not swapped:
53-
break # Stop iteration if the collection is sorted.
41+
break
42+
5443
return collection
5544

5645

57-
def bubble_sort_recursive(collection: list[Any]) -> list[Any]:
58-
"""It is similar iterative bubble sort but recursive.
59-
60-
:param collection: mutable ordered sequence of elements
61-
:return: the same list in ascending order
62-
63-
Examples:
64-
>>> bubble_sort_recursive([0, 5, 2, 3, 2])
65-
[0, 2, 2, 3, 5]
66-
>>> bubble_sort_iterative([])
67-
[]
68-
>>> bubble_sort_recursive([-2, -45, -5])
69-
[-45, -5, -2]
70-
>>> bubble_sort_recursive([-23, 0, 6, -4, 34])
71-
[-23, -4, 0, 6, 34]
72-
>>> bubble_sort_recursive([0, 5, 2, 3, 2]) == sorted([0, 5, 2, 3, 2])
73-
True
74-
>>> bubble_sort_recursive([]) == sorted([])
75-
True
76-
>>> bubble_sort_recursive([-2, -45, -5]) == sorted([-2, -45, -5])
77-
True
78-
>>> bubble_sort_recursive([-23, 0, 6, -4, 34]) == sorted([-23, 0, 6, -4, 34])
79-
True
80-
>>> bubble_sort_recursive(['d', 'a', 'b', 'e']) == sorted(['d', 'a', 'b', 'e'])
81-
True
82-
>>> bubble_sort_recursive(['z', 'a', 'y', 'b', 'x', 'c'])
83-
['a', 'b', 'c', 'x', 'y', 'z']
84-
>>> bubble_sort_recursive([1.1, 3.3, 5.5, 7.7, 2.2, 4.4, 6.6])
85-
[1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7]
86-
>>> bubble_sort_recursive([1, 3.3, 5, 7.7, 2, 4.4, 6])
87-
[1, 2, 3.3, 4.4, 5, 6, 7.7]
88-
>>> bubble_sort_recursive(['a', 'Z', 'B', 'C', 'A', 'c'])
89-
['A', 'B', 'C', 'Z', 'a', 'c']
90-
>>> import random
91-
>>> collection_arg = random.sample(range(-50, 50), 100)
92-
>>> bubble_sort_recursive(collection_arg) == sorted(collection_arg)
93-
True
94-
>>> import string
95-
>>> collection_arg = random.choices(string.ascii_letters + string.digits, k=100)
96-
>>> bubble_sort_recursive(collection_arg) == sorted(collection_arg)
97-
True
46+
def bubble_sort_optimized(collection: List[Any]) -> List[Any]:
9847
"""
99-
length = len(collection)
100-
swapped = False
101-
for i in range(length - 1):
102-
if collection[i] > collection[i + 1]:
103-
collection[i], collection[i + 1] = collection[i + 1], collection[i]
104-
swapped = True
105-
106-
return collection if not swapped else bubble_sort_recursive(collection)
107-
108-
109-
if __name__ == "__main__":
110-
import doctest
111-
from random import sample
112-
from timeit import timeit
113-
114-
doctest.testmod()
115-
116-
# Benchmark: Iterative seems slightly faster than recursive.
117-
num_runs = 10_000
118-
unsorted = sample(range(-50, 50), 100)
119-
timer_iterative = timeit(
120-
"bubble_sort_iterative(unsorted[:])", globals=globals(), number=num_runs
121-
)
122-
print("\nIterative bubble sort:")
123-
print(*bubble_sort_iterative(unsorted), sep=",")
124-
print(f"Processing time (iterative): {timer_iterative:.5f}s for {num_runs:,} runs")
125-
126-
unsorted = sample(range(-50, 50), 100)
127-
timer_recursive = timeit(
128-
"bubble_sort_recursive(unsorted[:])", globals=globals(), number=num_runs
129-
)
130-
print("\nRecursive bubble sort:")
131-
print(*bubble_sort_recursive(unsorted), sep=",")
132-
print(f"Processing time (recursive): {timer_recursive:.5f}s for {num_runs:,} runs")
48+
Optimized Bubble Sort
49+
50+
Uses the last swap position to reduce unnecessary comparisons
51+
when part of the list is already sorted.
52+
53+
:param collection: A mutable list of comparable elements
54+
:return: Sorted list
55+
"""
56+
57+
n = len(collection)
58+
if n < 2:
59+
return collection
60+
61+
while n > 1:
62+
last_swap = 0
63+
for i in range(1, n):
64+
if collection[i - 1] > collection[i]:
65+
collection[i - 1], collection[i] = collection[i], collection[i - 1]
66+
last_swap = i
67+
n = last_swap
68+
69+
return collection

0 commit comments

Comments
 (0)