Skip to content

Commit ed06bee

Browse files
committed
Initial commit.
0 parents  commit ed06bee

File tree

6 files changed

+242
-0
lines changed

6 files changed

+242
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/env/
2+
/__pycache__/
3+
/.vscode/

main.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import sorting as s
2+
import visualizer as vs
3+
import numpy as np
4+
import random
5+
6+
7+
def get_random_array():
8+
n = list(range(100))
9+
random.shuffle(n)
10+
return n
11+
12+
13+
arr = s.Array(get_random_array())
14+
s.selection_sort(arr)
15+
vs.show()

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
numpy
2+
matplotlib

sorting.py

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
from time import sleep
2+
import visualizer as vs
3+
4+
5+
class Array:
6+
7+
def __init__(self, values):
8+
self.values = list(values)
9+
10+
def swap(self, index1, index2):
11+
self.values[index2], self.values[index1] = self.values[index1], self.values[index2]
12+
vs.plot(self.values)
13+
14+
def set(self, index, num):
15+
self.values[index] = num
16+
vs.plot(self.values)
17+
18+
def getLen(self):
19+
return len(self.values)
20+
21+
22+
def bubble_sort(nums): # n^2
23+
# We set swapped to True so the loop looks runs at least once
24+
swapped = True
25+
while swapped:
26+
swapped = False
27+
for i in range(nums.getLen() - 1):
28+
if nums.values[i] > nums.values[i + 1]:
29+
# Swap the elements
30+
nums.swap(i, i + 1)
31+
# Set the flag to True so we'll loop again
32+
swapped = True
33+
34+
35+
def selection_sort(nums): # n^2
36+
# This value of i corresponds to how many values were sorted
37+
for i in range(nums.getLen()):
38+
# We assume that the first item of the unsorted segment is the smallest
39+
lowest_value_index = i
40+
# This loop iterates over the unsorted items
41+
for j in range(i + 1, nums.getLen()):
42+
if nums.values[j] < nums.values[lowest_value_index]:
43+
lowest_value_index = j
44+
# Swap values of the lowest unsorted element with the first unsorted
45+
# element
46+
nums.swap(i, lowest_value_index)
47+
48+
49+
def insertion_sort(nums): # n^2
50+
# Start on the second element as we assume the first element is sorted
51+
for i in range(1, nums.getLen()):
52+
item_to_insert = nums.values[i]
53+
# And keep a reference of the index of the previous element
54+
j = i - 1
55+
# Move all items of the sorted segment forward if they are larger than
56+
# the item to insert
57+
while j >= 0 and nums.values[j] > item_to_insert:
58+
nums.set(j + 1, nums.values[j])
59+
j -= 1
60+
# Insert the item
61+
nums.set(j + 1, item_to_insert)
62+
63+
64+
def heap_sort(nums): # n * logn
65+
66+
def heapify(nums, heap_size, root_index):
67+
# Assume the index of the largest element is the root index
68+
largest = root_index
69+
left_child = (2 * root_index) + 1
70+
right_child = (2 * root_index) + 2
71+
72+
# If the left child of the root is a valid index, and the element is greater
73+
# than the current largest element, then update the largest element
74+
if left_child < heap_size and nums.values[left_child] > nums.values[largest]:
75+
largest = left_child
76+
77+
# Do the same for the right child of the root
78+
if right_child < heap_size and nums.values[right_child] > nums.values[largest]:
79+
largest = right_child
80+
81+
# If the largest element is no longer the root element, swap them
82+
if largest != root_index:
83+
nums.swap(root_index, largest)
84+
# Heapify the new root element to ensure it's the largest
85+
heapify(nums, heap_size, largest)
86+
87+
n = nums.getLen()
88+
89+
# Create a Max Heap from the list
90+
# The 2nd argument of range means we stop at the element before -1 i.e.
91+
# the first element of the list.
92+
# The 3rd argument of range means we iterate backwards, reducing the count
93+
# of i by 1
94+
for i in range(n, -1, -1):
95+
heapify(nums, n, i)
96+
97+
# Move the root of the max heap to the end of
98+
for i in range(n - 1, 0, -1):
99+
nums.swap(i, 0)
100+
heapify(nums, i, 0)
101+
102+
103+
def merge_sort(nums): # n * logn
104+
105+
def merge(left_list, right_list):
106+
sorted_list = []
107+
left_list_index = right_list_index = 0
108+
109+
# We use the list lengths often, so its handy to make variables
110+
left_list_length, right_list_length = len(left_list), len(right_list)
111+
112+
for _ in range(left_list_length + right_list_length):
113+
if left_list_index < left_list_length and right_list_index < right_list_length:
114+
# We check which value from the start of each list is smaller
115+
# If the item at the beginning of the left list is smaller, add it
116+
# to the sorted list
117+
if left_list[left_list_index] <= right_list[right_list_index]:
118+
sorted_list.append(left_list[left_list_index])
119+
left_list_index += 1
120+
# If the item at the beginning of the right list is smaller, add it
121+
# to the sorted list
122+
else:
123+
sorted_list.append(right_list[right_list_index])
124+
right_list_index += 1
125+
126+
# If we've reached the end of the of the left list, add the elements
127+
# from the right list
128+
elif left_list_index == left_list_length:
129+
sorted_list.append(right_list[right_list_index])
130+
right_list_index += 1
131+
# If we've reached the end of the of the right list, add the elements
132+
# from the left list
133+
elif right_list_index == right_list_length:
134+
sorted_list.append(left_list[left_list_index])
135+
left_list_index += 1
136+
137+
return sorted_list
138+
139+
# If the list is a single element, return it
140+
if nums.getLen() <= 1:
141+
return nums
142+
143+
# Use floor division to get midpoint, indices must be integers
144+
mid = nums.getLen() // 2
145+
146+
# Sort and merge each half
147+
left_list = merge_sort(nums.values[:mid])
148+
right_list = merge_sort(nums.values[mid:])
149+
150+
# Merge the sorted lists into a new one
151+
return merge(left_list, right_list)
152+
153+
154+
def quick_sort(nums): # n^2
155+
def partition(nums, low, high):
156+
# We select the middle element to be the pivot. Some implementations select
157+
# the first element or the last element. Sometimes the median value becomes
158+
# the pivot, or a random one. There are many more strategies that can be
159+
# chosen or created.
160+
pivot = nums.values[(low + high) // 2]
161+
i = low - 1
162+
j = high + 1
163+
while True:
164+
i += 1
165+
while nums.values[i] < pivot:
166+
i += 1
167+
168+
j -= 1
169+
while nums.values[j] > pivot:
170+
j -= 1
171+
172+
if i >= j:
173+
return j
174+
175+
# If an element at i (on the left of the pivot) is larger than the
176+
# element at j (on right right of the pivot), then swap them
177+
nums.swap(j, i)
178+
179+
# Create a helper function that will be called recursively
180+
def _quick_sort(items, low, high):
181+
if low < high:
182+
# This is the index after the pivot, where our lists are split
183+
split_index = partition(items, low, high)
184+
_quick_sort(items, low, split_index)
185+
_quick_sort(items, split_index + 1, high)
186+
187+
_quick_sort(nums, 0, nums.getLen() - 1)

test.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import sorting as s
2+
import numpy as np
3+
4+
5+
def is_sorted(arr):
6+
return all(arr[i] <= arr[i+1] for i in range(len(arr)-1))
7+
8+
9+
def test(sorting_function):
10+
arr = s.Array(np.random.randint(low=-2000, high=2000, size=1000))
11+
sorting_function(arr)
12+
return 'Passed' if is_sorted(arr.values) else 'FAIL'
13+
14+
15+
functions = [s.bubble_sort, s.heap_sort, s.selection_sort,
16+
s.insertion_sort, s.quick_sort]
17+
for function in functions:
18+
print('Testing: ', function.__name__.ljust(16), test(function))

visualizer.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import matplotlib.pyplot as plt
2+
import matplotlib.animation as animation
3+
4+
5+
def plot(arr):
6+
plt.clf()
7+
plt.bar(range(len(arr)), arr, align='edge', width=1, data=arr)
8+
plt.pause(0.001)
9+
10+
11+
def show():
12+
plt.show()
13+
14+
15+
fig, graph = plt.subplots()
16+
graph.yaxis.set_visible(False)
17+
graph.xaxis.set_visible(False)

0 commit comments

Comments
 (0)