-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsort.py
364 lines (281 loc) · 9.91 KB
/
sort.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
import time
from typing import Union
from settings import *
def terminate() -> None:
status['sorting'] = False
status['playing'].clear()
selected['alg'] = None
selected['function'] = None
selected['text'] = ''
def swap(array: list, rect1: int, rect2: int) -> None:
# Store the two rectangles' index and positions
swap_rect['rect1'] = rect1
swap_rect['rect2'] = rect2
swap_rect['rect1_pos'] = array[rect1].x
swap_rect['rect2_pos'] = array[rect2].x
# Begin swapping process on the GUI
if status['sorting']:
status['swapping'] = True
while status['swapping']:
time.sleep(0.01)
# Swap elements
array[rect1], array[rect2] = array[rect2], array[rect1]
# Bubble Sort
def bubble_sort(array: list, size: int) -> None:
i = 0
while i < size - 1 and status['sorting']:
j = 0
while j < size - i - 1 and status['sorting']:
# Highlight the two elements being compared
array[j].color = RED
array[j+1].color = RED
time.sleep(Speed.delay)
if array[j].num > array[j+1].num:
# Swap elements
swap(array, j, j + 1)
# Pause if requested by user
status['playing'].wait()
# Abort sorting operation if user clicked on "Stop"
if not status['sorting']: break
array[j].color = WHITE
array[j+1].color = WHITE
j += 1
i += 1
terminate()
return
# Selection Sort
def selection_sort(array: list, size: int) -> None:
i = 0
min_index = i
while i < size and status['sorting']:
min_index = i
# Pause if requested by user
status['playing'].wait()
# Abort sorting operation if user clicked on "Stop"
if not status['sorting']: break
# Highlight the rectangle with the minimum value
if status['sorting']: array[min_index].color = RED
time.sleep(Speed.delay)
j = i + 1
while j < size and status['sorting']:
# Highlight the rectangle being scanned
array[j].color = RED
# Pause if requested by user
status['playing'].wait()
# Abort sorting operation if user clicked on "Stop"
if not status['sorting']: break
time.sleep(Speed.delay)
# Update current value to minimum value if current value if smaller than current minimum value
if array[j].num < array[min_index].num:
array[min_index].color = WHITE
min_index = j
else:
array[j].color = WHITE
j += 1
# Swap elements
swap(array, i, min_index)
array[i].color = WHITE
array[min_index].color = WHITE
i += 1
array[min_index].color = WHITE
terminate()
return
# Insertion Sort
def insertion_sort(array: list, size: int) -> None:
index = 1
while index < size and status['sorting']:
i = index
j = i - 1
# Pause if requested by user
status['playing'].wait()
# Abort sorting operation if user clicked on "Stop"
if not status['sorting']: break
while array[i].num < array[j].num and j >= 0 and status['sorting']:
# Highlight the two elements being compared
array[i].color = RED
array[j].color = RED
time.sleep(Speed.delay)
# Swap elements
swap(array, j, i)
# Pause if requested by user
status['playing'].wait()
# Abort sorting operation if user clicked on "Stop"
if not status['sorting']: break
array[i].color = WHITE
array[j].color = WHITE
i -= 1
j -= 1
# Highlight the two elements being compared
array[index].color = RED
array[index-1].color = RED
time.sleep(Speed.delay)
array[index].color = WHITE
array[index-1].color = WHITE
index += 1
terminate()
return
# Quick Sort
def quick_sort(array: list, end: int, start: int=0) -> None:
# Abort sorting operation if user clicked on "Stop"
if not status['sorting']: return
# Base case
if end <= start: return
# Set the length and height of the pivot line
quick_sort_line['start'] = (array[start].x, array[start].y)
quick_sort_line['end'] = (array[end - 1].x, array[end - 1].y)
# Gray out the other rectangles that arent being compared in the current stack
for rect in array:
rect.border = HOVER
rect.text_color = HOVER
for i in range(start, end):
array[i].border = BLACK
array[i].text_color = BLACK
pivot = partition(array, start, end - 1)
# Pause if requested by user
status['playing'].wait()
quick_sort(array, start=start, end=pivot)
quick_sort(array, start=pivot + 1, end=end)
if end - start == len(array):
# Reset all the rectangle's colors
for rect in array:
rect.border = BLACK
rect.text_color = BLACK
terminate()
return
# Helper function for quick sort
def partition(array: list, start: int, end: int) -> int:
# Set j as start and i as the element before start
j = start
i = start - 1
# Highlight the rectangle that is set as pivot
array[end].color = RED
while j < end + 1 and status['sorting']:
# Hightlight elements being compared
if i >= start: array[i].color = RED
array[j].color = RED
time.sleep(Speed.delay)
if array[j].num < array[end].num:
if i >= start: array[i].color = WHITE
i += 1
array[i].color = RED
if i != j: time.sleep(Speed.delay)
# Swap elements
swap(array, i, j)
# Pause if requested by user
status['playing'].wait()
# Abort sorting operation if user clicked on "Stop"
if not status['sorting']: break
array[j].color = WHITE
j += 1
array[i].color = WHITE
i += 1
array[end].color = RED
# Swap elements
swap(array, i, end)
array[i].color = WHITE
array[end].color = WHITE
return i
# Merge Sort
def merge_sort(array: list, end: int, start: int=0) -> None:
# Move rectangles up from initial call stack
if end - start == len(array):
shift_rectangles()
# Abort sorting operation if user clicked on "Stop"
if not status['sorting']:
# Move rectangles down
shift_rectangles()
terminate()
return
# Pause if requested by user
status['playing'].wait()
# Gray out the other rectangles that arent being compared in the current stack
for rect in array:
rect.border = HOVER
rect.text_color = HOVER
for i in range(start, end):
array[i].border = BLACK
array[i].text_color = BLACK
time.sleep(Speed.delay * 2)
# Base case
if end - start == 1: return
# Determine midpoint
mid = (start + end) // 2
merge_sort(array, start=start, end=mid)
merge_sort(array, start=mid, end=end)
# Highlight rectangles in subarray
for k in range(start, end):
array[k].border = BLACK
array[k].text_color = BLACK
# Abort sorting operation if user clicked on "Stop"
if not status['sorting']: return
merge(array, start, mid, end)
# Pause if requested by user
status['playing'].wait()
# Terminate sorting operation from initial call stack
if end - start == len(array):
status['sorting'] = False
# Move rectangles down
shift_rectangles()
terminate()
return
def merge(array, start, mid, end):
# Create a temporary array for storing sorted subarray
temp = []
i, j = start, mid
start_pos = array[start].x
# Abort sorting operation if user clicked on "Stop"
if not status['sorting']: return
time.sleep(Speed.delay * 2)
while i < mid and j < end:
# Pause if requested by user
status['playing'].wait()
if array[i].num < array[j].num:
# Sort subarray
sort_subarray_gui(array, i, start_pos + (RECT_WIDTH + RECT_SPACING) * (len(temp)))
temp.append(array[i])
i += 1
else:
# Sort subarray
sort_subarray_gui(array, j, start_pos + (RECT_WIDTH + RECT_SPACING) * (len(temp)))
temp.append(array[j])
j += 1
while i < mid:
# Pause if requested by user
status['playing'].wait()
# Sort subarray
sort_subarray_gui(array, i, start_pos + (RECT_WIDTH + RECT_SPACING) * len(temp))
temp.append(array[i])
i += 1
while j < end:
# Pause if requested by user
status['playing'].wait()
# Sort subarray
sort_subarray_gui(array, j, start_pos + (RECT_WIDTH + RECT_SPACING) * len(temp))
temp.append(array[j])
j += 1
# Pause if requested by user
status['playing'].wait()
# Merge rectangles
for k in range(end - start):
array[start + k] = temp[k]
merge_subarray_gui(start, end)
def shift_rectangles() -> None:
status['moving'] = True
while status['moving']:
time.sleep(0.01)
def sort_subarray_gui(array: list, index: int, stopping_pos: Union[int, float]) -> None:
# Store the rectangle's index and position
sub_sort['rect'] = index
sub_sort['rect_x_pos'] = array[index].x
# Store the rectangle's stopping position
sub_sort['rect_pos_dest'] = stopping_pos
# Begin subarray sorting process on the GUI
status['sub_sorting'] = True
while status['sub_sorting']:
time.sleep(0.01)
def merge_subarray_gui(start: int, end: int) -> None:
# Begin merging process on the GUI
merge_rect[0], merge_rect[1] = start, end
status['merging'] = True
while status['merging']:
time.sleep(0.01)