1

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()

1 Answers1

1

enter image description here

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()
furas
  • 134,197
  • 12
  • 106
  • 148