MAHATMA EDUCATION SOCIETY’S
PILLAI COLLEGE OF ARTS, COMMERCE & SCIENCE
(Autonomous)
NEW PANVEL
PROJECT REPORT ON
“Sorting Algorithm Visualizer”
IN PARTIAL FULFILLMENT OF
BACHELOR OF COMPUTER SCIENCE
SEMESTER III – 2025-26
UNDER THE GUIDANCE OF
Mrs.Anuradha Singh
SUBMITTED BY: Dhanashri Ananda Achare
ROLL NO:5254
1
Index
Sr.No. Topic Page No.
1 Introduction 3
2 List Of Methods 4
3 Code 5
4 Output 14
5 Conclusion & 20
References
2
Introdution
Sorting is one of the most fundamental operations in computer science and plays
a crucial role in data organization, searching, and optimization. Different sorting
algorithms follow unique strategies and approaches, each with its own
advantages, disadvantages, and time complexity. Understanding the working of
these algorithms is essential for students and professionals alike.
The Sorting Grid Visualizer is a Python-based desktop application developed
using the Tkinter library. Its primary objective is to provide a clear, step-by-step
visualization of how various sorting algorithms work. The application allows
users to enter custom numerical data, choose a sorting algorithm, and specify the
order (ascending or descending).
As the sorting progresses, the program captures each intermediate step (iteration)
and displays it in a grid format. This visual representation helps users observe
how elements move, swap, or get inserted during the sorting process. By
navigating through the iterations, learners can gain a deeper understanding of the
internal mechanics of each algorithm.
The application supports the following algorithms:
• Bubble Sort
• Selection Sort
• Insertion Sort
• Quick Sort
• Merge Sort
Through this project, the complex concept of sorting is simplified with the help
of graphical visualization, making it an effective educational tool for both
beginners and enthusiasts.
3
List of methods
Here’s a detailed explanation of the main methods/functions in the project:
• init__(self, root) – Initializes the main window, variables, and loads
default data.
• setup_ui(self) – Builds the GUI layout including frames, labels, buttons,
dropdowns, and canvas.
• use_custom_data(self) – Reads custom comma-separated input from the
user and prepares it for sorting.
• draw_grid(self) – Displays sorting iterations in a grid format with iteration
numbers and data values.
• bubble_sort(self, ascending=True) – Performs Bubble Sort on the dataset
and records each step.
• selection_sort(self, ascending=True) – Performs Selection Sort and
appends each iteration to the list.
• insertion_sort(self, ascending=True) – Performs Insertion Sort and
tracks changes after each insertion.
• quick_sort(self, ascending=True) – Implements Quick Sort recursively
and saves intermediate states.
• partition(self, arr, low, high, ascending) – Helper method for Quick Sort
that partitions data around a pivot.
• merge_sort(self, ascending=True) – Implements Merge Sort recursively
and stores merged steps.
• start_sorting(self) – Executes the selected sorting algorithm and resets the
iteration tracker.
• prev_iteration(self) – Moves one step backward in the sorting
visualization.
• next_iteration(self) – Moves one step forward in the sorting visualization.
• reset(self) – Resets the visualization to the original input data entered by
the user.
4
Code
• main.py
import tkinter as tk
from tkinter import ttk, messagebox
class SortingGridVisualizer:
def __init__(self, root):
self.root = root
self.root.title("Sorting Grid Visualizer")
self.root.geometry("900x700")
self.data = []
self.iterations = []
self.current_iteration = 0
self.sorting = False
self.algorithm = tk.StringVar(value="Bubble Sort")
self.order = tk.StringVar(value="Descending")
self.data_input = tk.StringVar(value="12,34,56,10,34")
self.setup_ui()
self.use_custom_data()
def setup_ui(self):
container = ttk.Frame(self.root)
container.pack(expand=True, fill=tk.BOTH, padx=20, pady=20)
control_frame = ttk.Frame(container)
control_frame.pack(pady=10, fill=tk.X)
ttk.Label(control_frame, text="Algorithm:").grid(row=0, column=0,
padx=5)
algorithms = ["Bubble Sort", "Selection Sort", "Insertion Sort",
"Quick Sort", "Merge Sort"]
self.algorithm_menu = ttk.Combobox(control_frame,
textvariable=self.algorithm, values=algorithms, width=12)
self.algorithm_menu.grid(row=0, column=1, padx=5)
ttk.Label(control_frame, text="Order:").grid(row=0, column=2, padx=5)
self.order_menu = ttk.Combobox(control_frame, textvariable=self.order,
values=["Ascending", "Descending"], width=10)
self.order_menu.grid(row=0, column=3, padx=5)
input_frame = ttk.Frame(container)
input_frame.pack(fill=tk.X, pady=10)
5
ttk.Label(input_frame, text="Enter Data (comma
separated):").pack(side=tk.LEFT, padx=5)
self.data_entry = ttk.Entry(input_frame, textvariable=self.data_input,
width=30)
self.data_entry.pack(side=tk.LEFT, padx=5)
ttk.Button(input_frame, text="Use This Data",
command=self.use_custom_data).pack(side=tk.LEFT, padx=5)
button_frame = ttk.Frame(container)
button_frame.pack(pady=5)
ttk.Button(button_frame, text="Start Sorting",
command=self.start_sorting).pack(side=tk.LEFT, padx=5)
ttk.Button(button_frame, text="Reset",
command=self.reset).pack(side=tk.LEFT, padx=5)
ttk.Button(button_frame, text="Previous",
command=self.prev_iteration).pack(side=tk.LEFT, padx=5)
ttk.Button(button_frame, text="Next",
command=self.next_iteration).pack(side=tk.LEFT, padx=5)
self.canvas_frame = ttk.Frame(container, relief=tk.SUNKEN,
borderwidth=2)
self.canvas_frame.pack(expand=True, fill=tk.BOTH, pady=10)
self.canvas = tk.Canvas(self.canvas_frame, bg="white",
highlightthickness=0)
self.canvas.pack(expand=True, fill=tk.BOTH, padx=10, pady=10)
self.scrollbar = ttk.Scrollbar(self.canvas_frame, orient=tk.VERTICAL,
command=self.canvas.yview)
self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.canvas.configure(yscrollcommand=self.scrollbar.set)
self.status_label = ttk.Label(container, text="Ready",
font=('Helvetica', 10, 'bold'))
self.status_label.pack(pady=5)
def use_custom_data(self):
if self.sorting:
return
input_str = self.data_input.get()
try:
custom_data = [int(x.strip()) for x in input_str.split(",") if
x.strip()]
if not custom_data:
messagebox.showerror("Error", "Please enter valid numbers
separated by commas")
6
return
self.data = custom_data
self.iterations = [self.data.copy()]
self.current_iteration = 0
self.draw_grid()
self.status_label.config(text=f"Using {len(self.data)} numbers:
{self.data}")
except ValueError:
messagebox.showerror("Error", "Please enter only numbers separated
by commas")
def draw_grid(self):
self.canvas.delete("all")
if not self.iterations:
return
current_data = self.iterations[self.current_iteration]
cols = len(current_data)
rows = len(self.iterations)
iter_col_width = 60
data_col_width = 70
cell_height = 35
row_spacing = 5
y = 10
self.canvas.create_rectangle(0, y, iter_col_width, y + cell_height,
fill="#f0f0f0", outline="black")
self.canvas.create_text(iter_col_width/2, y + cell_height/2,
text="Iter", font=('Helvetica', 10, 'bold'))
for col in range(cols):
x = iter_col_width + col * data_col_width
self.canvas.create_rectangle(x, y, x + data_col_width, y +
cell_height, fill="#f0f0f0", outline="black")
self.canvas.create_text(x + data_col_width/2, y + cell_height/2,
text=str(col), font=('Helvetica', 10, 'bold'))
y += cell_height + row_spacing
for row in range(rows):
row_color = "#e6f3ff" if row == self.current_iteration else
"white"
7
self.canvas.create_rectangle(0, y, iter_col_width, y +
cell_height, fill="#f0f0f0", outline="black")
self.canvas.create_text(iter_col_width/2, y + cell_height/2,
text=str(row), font=('Helvetica', 9))
for col, value in enumerate(self.iterations[row]):
x = iter_col_width + col * data_col_width
self.canvas.create_rectangle(x, y, x + data_col_width, y +
cell_height, fill=row_color, outline="black")
self.canvas.create_text(x + data_col_width/2, y +
cell_height/2, text=str(value), font=('Helvetica', 9))
y += cell_height + row_spacing
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
self.status_label.config(text=f"Iteration {self.current_iteration} of
{len(self.iterations)-1}")
def bubble_sort(self, ascending=True):
n = len(self.data)
for i in range(n):
swapped = False
for j in range(0, n-i-1):
if (ascending and self.data[j] > self.data[j+1]) or (not
ascending and self.data[j] < self.data[j+1]):
self.data[j], self.data[j+1] = self.data[j+1],
self.data[j]
swapped = True
self.iterations.append(self.data.copy())
if not swapped:
break
def selection_sort(self, ascending=True):
for i in range(len(self.data)):
extreme_index = i
for j in range(i+1, len(self.data)):
if (ascending and self.data[j] < self.data[extreme_index]) or
(not ascending and self.data[j] > self.data[extreme_index]):
extreme_index = j
self.data[i], self.data[extreme_index] = self.data[extreme_index],
self.data[i]
self.iterations.append(self.data.copy())
def insertion_sort(self, ascending=True):
for i in range(1, len(self.data)):
key = self.data[i]
j = i-1
8
while j >= 0 and ((ascending and key < self.data[j]) or (not
ascending and key > self.data[j])):
self.data[j+1] = self.data[j]
j -= 1
self.data[j+1] = key
self.iterations.append(self.data.copy())
def quick_sort(self, ascending=True):
def _quick_sort(arr, low, high):
if low < high:
pi = self.partition(arr, low, high, ascending)
self.iterations.append(self.data.copy())
_quick_sort(arr, low, pi-1)
_quick_sort(arr, pi+1, high)
_quick_sort(self.data, 0, len(self.data)-1)
def partition(self, arr, low, high, ascending):
pivot = arr[high]
i = low - 1
for j in range(low, high):
if (ascending and arr[j] <= pivot) or (not ascending and arr[j] >=
pivot):
i += 1
arr[i], arr[j] = arr[j], arr[i]
arr[i+1], arr[high] = arr[high], arr[i+1]
return i+1
def merge_sort(self, ascending=True):
def _merge_sort(arr):
if len(arr) > 1:
mid = len(arr) // 2
L = arr[:mid]
R = arr[mid:]
_merge_sort(L)
_merge_sort(R)
i = j = k = 0
while i < len(L) and j < len(R):
if (ascending and L[i] <= R[j]) or (not ascending and L[i]
>= R[j]):
arr[k] = L[i]
i += 1
else:
arr[k] = R[j]
j += 1
9
k += 1
while i < len(L):
arr[k] = L[i]
i += 1
k += 1
while j < len(R):
arr[k] = R[j]
j += 1
k += 1
self.iterations.append(self.data.copy())
_merge_sort(self.data)
def start_sorting(self):
if self.sorting or not self.data:
return
self.sorting = True
self.iterations = [self.data.copy()]
algorithm = self.algorithm.get()
ascending = self.order.get() == "Ascending"
if algorithm == "Bubble Sort":
self.bubble_sort(ascending)
elif algorithm == "Selection Sort":
self.selection_sort(ascending)
elif algorithm == "Insertion Sort":
self.insertion_sort(ascending)
elif algorithm == "Quick Sort":
self.quick_sort(ascending)
elif algorithm == "Merge Sort":
self.merge_sort(ascending)
self.sorting = False
self.current_iteration = 0
self.draw_grid()
def prev_iteration(self):
if self.current_iteration > 0:
self.current_iteration -= 1
self.draw_grid()
def next_iteration(self):
if self.current_iteration < len(self.iterations) - 1:
10
self.current_iteration += 1
self.draw_grid()
def reset(self):
if self.sorting:
return
self.use_custom_data()
if __name__ == "__main__":
root = tk.Tk()
app = SortingGridVisualizer(root)
root.mainloop()
• sorting_algorithms.py
def bubble_sort(data, ascending=True):
n = len(data)
iterations = []
for i in range(n):
swapped = False
for j in range(0, n-i-1):
if ascending:
if data[j] > data[j+1]:
data[j], data[j+1] = data[j+1], data[j]
swapped = True
else:
if data[j] < data[j+1]:
data[j], data[j+1] = data[j+1], data[j]
swapped = True
iterations.append(data.copy())
if not swapped:
break
return iterations
def selection_sort(data, ascending=True):
iterations = []
for i in range(len(data)):
extreme_index = i
for j in range(i+1, len(data)):
if ascending:
if data[j] < data[extreme_index]:
extreme_index = j
else:
if data[j] > data[extreme_index]:
extreme_index = j
data[i], data[extreme_index] = data[extreme_index], data[i]
iterations.append(data.copy())
return iterations
11
def insertion_sort(data, ascending=True):
iterations = []
for i in range(1, len(data)):
key = data[i]
j = i-1
if ascending:
while j >= 0 and key < data[j]:
data[j+1] = data[j]
j -= 1
else:
while j >= 0 and key > data[j]:
data[j+1] = data[j]
j -= 1
data[j+1] = key
iterations.append(data.copy())
return iterations
def quick_sort(data, ascending=True):
iterations = []
def _quick_sort(arr, low, high):
if low < high:
pi = partition(arr, low, high)
iterations.append(arr.copy())
_quick_sort(arr, low, pi-1)
_quick_sort(arr, pi+1, high)
def partition(arr, low, high):
pivot = arr[high]
i = low - 1
for j in range(low, high):
if ascending:
if arr[j] <= pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i]
else:
if arr[j] >= pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i]
arr[i+1], arr[high] = arr[high], arr[i+1]
return i+1
_quick_sort(data, 0, len(data)-1)
return iterations
def merge_sort(data, ascending=True):
iterations = []
12
def _merge_sort(arr):
if len(arr) > 1:
mid = len(arr) // 2
L = arr[:mid]
R = arr[mid:]
_merge_sort(L)
_merge_sort(R)
i = j = k = 0
while i < len(L) and j < len(R):
if ascending:
if L[i] <= R[j]:
arr[k] = L[i]
i += 1
else:
arr[k] = R[j]
j += 1
else:
if L[i] >= R[j]:
arr[k] = L[i]
i += 1
else:
arr[k] = R[j]
j += 1
k += 1
while i < len(L):
arr[k] = L[i]
i += 1
k += 1
while j < len(R):
arr[k] = R[j]
j += 1
k += 1
iterations.append(arr.copy())
_merge_sort(data)
return iterations
13
Output
• Initial screen:
• Sorting data in ascending order using bubble sort:
14
• Sorting data in descending order using bubble sort:
• Sorting data in ascending order using selection sort:
15
• Sorting data in descending order using selection sort:
• Sorting data in ascending order using insertion sort:
16
• Sorting data in descending order using insertion sort:
• Sorting data in ascending order using quick sort:
17
• Sorting data in descending order using quick sort:
• Sorting data in ascending order using merge sort:
18
• Sorting data in descending order using merge sort:
• Traversing through the iteration (using previous and next button):
19
Conclusion
The Sorting Algorithm Visualizer using Python (Tkinter) successfully provides
an interactive way to understand and analyze the working of different sorting
algorithms, including Bubble Sort, Selection Sort, Insertion Sort, Quick Sort, and
Merge Sort. By presenting each step in a grid-based visualization, the project
simplifies complex algorithmic operations and makes learning more engaging for
students. It not only strengthens conceptual clarity but also highlights the role of
visualization in education, while leaving scope for future enhancements such as
adding more algorithms, measuring performance, or integrating animations.
Reference
https://docs.python.org/3/library/tkinter.html - Tkinter - Python's Standard
GUI Package
https://www.amazon.com/Python-GUI-Programming-Tkinter-Addison-
Wesley/dp/0135159946 - Python GUI Programming with Tkinter
https://www.geeksforgeeks.org/sorting-algorithms/- Sorting Algorithms –
GeeksforGeeks
https://www.programiz.com/dsa/sorting-algorithm- Python Sorting
Algorithms
20