Skip to content

Commit 3bf12b0

Browse files
authored
Create Cocktail Shaker Sort.py
1 parent d4a0be9 commit 3bf12b0

File tree

1 file changed

+238
-0
lines changed

1 file changed

+238
-0
lines changed
Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
def cocktail_shaker_sort(arr):
2+
"""
3+
Cocktail Shaker Sort (also called Bidirectional Bubble Sort, Ripple Sort)
4+
Time Complexity: O(n^2) worst/average case, O(n) best case
5+
Space Complexity: O(1)
6+
7+
An improvement over Bubble Sort that traverses the list in both directions
8+
alternately. It's slightly better than Bubble Sort in practice because it
9+
moves both small and large elements to their positions more quickly.
10+
11+
Like shaking a cocktail shaker - elements move up and down!
12+
"""
13+
n = len(arr)
14+
swapped = True
15+
start = 0
16+
end = n - 1
17+
18+
while swapped:
19+
swapped = False
20+
21+
# Move from left to right (like bubble sort)
22+
# Move the largest element to the end
23+
for i in range(start, end):
24+
if arr[i] > arr[i + 1]:
25+
arr[i], arr[i + 1] = arr[i + 1], arr[i]
26+
swapped = True
27+
28+
if not swapped:
29+
break
30+
31+
# Reduce end since largest element is now at the end
32+
end -= 1
33+
swapped = False
34+
35+
# Move from right to left
36+
# Move the smallest element to the beginning
37+
for i in range(end - 1, start - 1, -1):
38+
if arr[i] > arr[i + 1]:
39+
arr[i], arr[i + 1] = arr[i + 1], arr[i]
40+
swapped = True
41+
42+
# Increase start since smallest element is now at the beginning
43+
start += 1
44+
45+
return arr
46+
47+
48+
def cocktail_sort_optimized(arr):
49+
"""
50+
Optimized version that remembers last swap position
51+
to avoid unnecessary comparisons
52+
"""
53+
n = len(arr)
54+
start = 0
55+
end = n - 1
56+
57+
while start < end:
58+
new_start = start
59+
new_end = end
60+
61+
# Forward pass
62+
for i in range(start, end):
63+
if arr[i] > arr[i + 1]:
64+
arr[i], arr[i + 1] = arr[i + 1], arr[i]
65+
new_end = i
66+
67+
end = new_end
68+
69+
# If no swaps in forward pass, array is sorted
70+
if start >= end:
71+
break
72+
73+
# Backward pass
74+
for i in range(end - 1, start - 1, -1):
75+
if arr[i] > arr[i + 1]:
76+
arr[i], arr[i + 1] = arr[i + 1], arr[i]
77+
new_start = i
78+
79+
start = new_start
80+
81+
return arr
82+
83+
84+
def cocktail_sort_with_visualization(arr):
85+
"""
86+
Cocktail Sort with step-by-step visualization
87+
"""
88+
n = len(arr)
89+
swapped = True
90+
start = 0
91+
end = n - 1
92+
pass_num = 0
93+
94+
print(f"Starting array: {arr}\n")
95+
96+
while swapped:
97+
swapped = False
98+
pass_num += 1
99+
100+
# Forward pass
101+
print(f"Pass {pass_num} - Forward (→):")
102+
for i in range(start, end):
103+
if arr[i] > arr[i + 1]:
104+
arr[i], arr[i + 1] = arr[i + 1], arr[i]
105+
swapped = True
106+
print(f" Swapped positions {i} and {i+1}: {arr}")
107+
108+
if not swapped:
109+
break
110+
111+
end -= 1
112+
swapped = False
113+
114+
# Backward pass
115+
print(f"Pass {pass_num} - Backward (←):")
116+
for i in range(end - 1, start - 1, -1):
117+
if arr[i] > arr[i + 1]:
118+
arr[i], arr[i + 1] = arr[i + 1], arr[i]
119+
swapped = True
120+
print(f" Swapped positions {i} and {i+1}: {arr}")
121+
122+
start += 1
123+
print(f"After pass {pass_num}: {arr}\n")
124+
125+
print(f"Sorted in {pass_num} passes!")
126+
return arr
127+
128+
129+
def compare_with_bubble_sort(arr):
130+
"""
131+
Compare Cocktail Sort with Bubble Sort
132+
"""
133+
def bubble_sort_count(arr):
134+
n = len(arr)
135+
swaps = 0
136+
for i in range(n):
137+
for j in range(0, n - i - 1):
138+
if arr[j] > arr[j + 1]:
139+
arr[j], arr[j + 1] = arr[j + 1], arr[j]
140+
swaps += 1
141+
return arr, swaps
142+
143+
def cocktail_sort_count(arr):
144+
n = len(arr)
145+
swapped = True
146+
start = 0
147+
end = n - 1
148+
swaps = 0
149+
150+
while swapped:
151+
swapped = False
152+
153+
for i in range(start, end):
154+
if arr[i] > arr[i + 1]:
155+
arr[i], arr[i + 1] = arr[i + 1], arr[i]
156+
swapped = True
157+
swaps += 1
158+
159+
if not swapped:
160+
break
161+
162+
end -= 1
163+
swapped = False
164+
165+
for i in range(end - 1, start - 1, -1):
166+
if arr[i] > arr[i + 1]:
167+
arr[i], arr[i + 1] = arr[i + 1], arr[i]
168+
swapped = True
169+
swaps += 1
170+
171+
start += 1
172+
173+
return arr, swaps
174+
175+
arr_bubble = arr.copy()
176+
arr_cocktail = arr.copy()
177+
178+
_, bubble_swaps = bubble_sort_count(arr_bubble)
179+
_, cocktail_swaps = cocktail_sort_count(arr_cocktail)
180+
181+
print(f"Original array: {arr}")
182+
print(f"Bubble Sort swaps: {bubble_swaps}")
183+
print(f"Cocktail Sort swaps: {cocktail_swaps}")
184+
print(f"Improvement: {bubble_swaps - cocktail_swaps} fewer swaps")
185+
print(f"Percentage: {((bubble_swaps - cocktail_swaps) / bubble_swaps * 100):.1f}% reduction")
186+
187+
188+
# Example usage
189+
if __name__ == "__main__":
190+
# Test case 1
191+
arr1 = [5, 1, 4, 2, 8, 0, 2]
192+
print("Original array:", arr1)
193+
print("Sorted array:", cocktail_shaker_sort(arr1.copy()))
194+
print()
195+
196+
# Test case 2
197+
arr2 = [64, 34, 25, 12, 22, 11, 90]
198+
print("Original array:", arr2)
199+
print("Sorted array:", cocktail_shaker_sort(arr2.copy()))
200+
print()
201+
202+
# Test case 3 - With visualization (small array)
203+
arr3 = [5, 2, 8, 1, 9]
204+
print("Sorting with visualization:")
205+
cocktail_sort_with_visualization(arr3.copy())
206+
print()
207+
208+
# Test case 4 - Already sorted
209+
arr4 = [1, 2, 3, 4, 5]
210+
print("Already sorted:", arr4)
211+
print("After sorting:", cocktail_shaker_sort(arr4.copy()))
212+
print()
213+
214+
# Test case 5 - Worst case for bubble sort (small at end)
215+
arr5 = [2, 3, 4, 5, 1]
216+
print("Worst case for bubble sort (turtle at end):")
217+
compare_with_bubble_sort(arr5)
218+
print()
219+
220+
# Test case 6 - Reverse sorted
221+
arr6 = [9, 8, 7, 6, 5, 4, 3, 2, 1]
222+
print("Reverse sorted:", arr6)
223+
print("After sorting:", cocktail_shaker_sort(arr6.copy()))
224+
print()
225+
226+
# Test case 7 - Optimized version
227+
arr7 = [5, 1, 4, 2, 8, 0, 2]
228+
print("Using optimized version:")
229+
print("Original:", arr7)
230+
print("Sorted:", cocktail_sort_optimized(arr7.copy()))
231+
print()
232+
233+
print("="*60)
234+
print("COCKTAIL SORT vs BUBBLE SORT:")
235+
print("-"*60)
236+
print("Cocktail Sort eliminates 'turtles' (small values at the end)")
237+
print("by traversing in both directions, making it faster in practice!")
238+
print("="*60)

0 commit comments

Comments
 (0)