I am making a series of articles about sorting algorithms, and the first part is about bubble sorting, I have the GUI elements in place, but the sorting algorithm itself is not working correctly. it randomly swaps a series of lines of different lengths, but the sorting doesn't work as expected. It is written in python Tkinter, I think the main problem comes from how I programmed the sorting like two lists, one on the screen and one on memory. It would be helpful if you could also explain my mistake to me.
import tkinter as tk
import random
def swap_two_pos(pos_0, pos_1):
"""This does the graphical swapping of the rectangles on the canvas
by moving one rectangle to the location of the other, and vice versa
"""
x_00, _, x_01, _ = canvas.coords(pos_0)
x_10, _, x_11, _ = canvas.coords(pos_1)
# moves each rectangle to the x position of the other; y remains unchanged
canvas.move(pos_0, x_10-x_00, 0)
canvas.move(pos_1, x_01-x_11, 0)
def sort_two(pos_0, pos_1):
x_00, y1, x_01, _ = canvas.coords(pos_0)
x_10, y2, x_11, _ = canvas.coords(pos_1)
# moves each rectangle to the x position of the other; y remains unchanged
if y2 > y1:
canvas.move(pos_0, x_10-x_00, 0)
canvas.move(pos_1, x_01-x_11, 0)
def rand_sort():
for i in range(50000):
rd1 = random.randint(0, 58)
rd2 = random.randint(0, 58)
pos_1 = barList[rd1]
pos_2 = barList[rd2]
sort_two(pos_1, pos_2)
barList[rd1], barList[rd2] = barList[rd2], barList[rd1]
def sort ():
n = len(barList)
# Traverse through all array elements
for i in range(n):
# Last i elements are already in place
for j in range(0, n-i-1):
sort_two(barList[j], barList[j+1])
barList[j], barList[j+1] = barList[j+1], barList[j]
else:
break
def random_swap():
"""Not a sort yet, but you have the bare bones operations
so the swap is executed
"""
for i in range(500):
rd1 = random.randint(0, 58)
rd2 = random.randint(0, 58)
pos_0 = barList[rd1]
pos_1 = barList[rd2]
swap_two_pos(pos_0, pos_1)
# it is necessary to swap the values in the list too
barList[rd1], barList[rd2] = barList[rd2], barList[rd1]
window = tk.Tk()
window.title('Sorting')
window.geometry('600x400')
# button to command the swap
tk.Button(window, text='swap', command=random_swap).pack()
tk.Button(window, text='sort', command=sort).pack()
xstart = 5
xend = 15
canvas = tk.Canvas(window, width='900', height='900')
canvas.pack()
barList = []
lengthList = []
Y = 5
for x in range(1,60):
bar = canvas.create_rectangle(xstart, Y, xend, 395, fill='red')
barList.append(bar)
xstart += 10
xend += 10
Y += 5
for bar in barList:
x = canvas.coords(bar)
length = x[3]-x[1]
lengthList.append(length)
window.mainloop()
The biggest problem is that inside sort_two
you have if
if y2 > y1:
canvas.move(pos_0, x_10-x_00, 0)
canvas.move(pos_1, x_01-x_11, 0)
which replaces elements only if y2 > y1
but after sort_two()
you use barList
sort_two(pos_1, pos_2)
barList[rd1], barList[rd2] = barList[rd2], barList[rd1]
which always replaces elements on list.
And this way you have wrong results on screen.
You could return True/False
from sort_two()
to control when to change elements on barList
if y2 > y1:
canvas.move(pos_0, x_10-x_00, 0)
canvas.move(pos_1, x_01-x_11, 0)
return True
else:
return False
and
if sort_two(pos_1, pos_2):
barList[rd1], barList[rd2] = barList[rd2], barList[rd1]
Here finall code
I use simple calculation for replacing elements on canvas
x1, _, _, _ = canvas.coords(pos_0)
x2, _, _, _ = canvas.coords(pos_1)
diff = x1 - x2
canvas.move(pos_0, -diff, 0)
canvas.move(pos_1, +diff, 0)
I also removed
else:
break
which stop animation after every replace and it needs to click button sort
again and again - and I use
window.update()
time.sleep(0.1)
so it displays animation (slowly) to the end of sorting and I don't have to click button sort
import tkinter as tk
import random
import time
def swap_two_pos(pos_0, pos_1):
"""This does the graphical swapping of the rectangles on the canvas
by moving one rectangle to the location of the other, and vice versa
"""
x1, _, _, _ = canvas.coords(pos_0)
x2, _, _, _ = canvas.coords(pos_1)
diff = x1 - x2
canvas.move(pos_0, -diff, 0)
canvas.move(pos_1, +diff, 0)
def sort_two(pos_0, pos_1):
x1, y1, _, _ = canvas.coords(pos_0)
x2, y2, _, _ = canvas.coords(pos_1)
diff = x1 - x2
# moves each rectangle to the x position of the other; y remains unchanged
if y2 > y1:
canvas.move(pos_0, -diff, 0)
canvas.move(pos_1, +diff, 0)
return True
else:
return False
def rand_sort():
for i in range(50000):
rd1 = random.randint(0, 58)
rd2 = random.randint(0, 58)
pos_1 = barList[rd1]
pos_2 = barList[rd2]
if sort_two(pos_1, pos_2):
barList[rd1], barList[rd2] = barList[rd2], barList[rd1]
def sort ():
n = len(barList)
# Traverse through all array elements
for i in range(n):
# Last i elements are already in place
for j in range(0, n-i-1):
if sort_two(barList[j], barList[j+1]):
barList[j], barList[j+1] = barList[j+1], barList[j]
window.update()
time.sleep(0.1)
def random_swap():
"""Not a sort yet, but you have the bare bones operations
so the swap is executed
"""
for i in range(500):
rd1 = random.randint(0, 58)
rd2 = random.randint(0, 58)
pos_0 = barList[rd1]
pos_1 = barList[rd2]
swap_two_pos(pos_0, pos_1)
# it is necessary to swap the values in the list too
barList[rd1], barList[rd2] = barList[rd2], barList[rd1]
window = tk.Tk()
window.title('Sorting')
window.geometry('600x400')
# button to command the swap
tk.Button(window, text='swap', command=random_swap).pack()
tk.Button(window, text='sort', command=sort).pack()
xstart = 5
xend = 15
canvas = tk.Canvas(window, width='900', height='900')
canvas.pack()
barList = []
lengthList = []
Y = 5
for x in range(1,60):
bar = canvas.create_rectangle(xstart, Y, xend, 395, fill='red')
barList.append(bar)
xstart += 10
xend += 10
Y += 5
for bar in barList:
x = canvas.coords(bar)
length = x[3]-x[1]
lengthList.append(length)
window.mainloop()