Skip to content

Commit 7897a9b

Browse files
committed
initial commit: visualizer
1 parent f412c72 commit 7897a9b

13 files changed

+819
-0
lines changed

README.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,100 @@
11
# sorting-visualizer
22
This Flask web app demonstrates the execution of sorting algorithms (Merge, Insertion, Selection etc.) Users can test algorithms on arrays provided directly, via files, or generated randomly, and compare performance on varying sizes. It features execution time visualizations (bar/line plots), result downloads, and aids in algorithm analysis.
3+
4+
5+
# Sorting Algorithm Performance Visualizer
6+
7+
This Flask web application allows users to test and compare the performance of various sorting algorithms on arrays of different sizes and types. It includes features for result visualization and downloading.
8+
9+
## Features
10+
11+
- **Input Options**:
12+
- Directly enter an array.
13+
- Upload a file containing an array.
14+
- Generate a random array of a specified size.
15+
16+
- **Execution Modes**:
17+
- Test a single array with selected sorting algorithms.
18+
- Compare multiple algorithms on arrays of varying sizes.
19+
20+
- **Visualization**:
21+
- Bar chart to compare execution times for a single array.
22+
- Line graph to show algorithm performance trends for varying input sizes.
23+
24+
- **Download Results**: Retrieve execution results as a `.txt` file.
25+
26+
## Algorithms Supported
27+
28+
- Merge Sort
29+
- Insertion Sort
30+
- Selection Sort
31+
- Bubble Sort
32+
- Quick Sort
33+
34+
## Installation
35+
36+
### Prerequisites
37+
- Python 3.7 or higher
38+
- pip (Python package manager)
39+
40+
### Setup
41+
1. Clone the repository:
42+
```bash
43+
git clone https://github.com/yourusername/sorting-visualizer.git
44+
cd sorting-visualizer
45+
46+
47+
48+
## Running the Application
49+
50+
### 1. Create a Virtual Environment
51+
Set up a Python virtual environment to isolate dependencies:
52+
```bash
53+
python -m venv venv
54+
55+
```
56+
Activate the environment:
57+
- On **Linux/Mac**:
58+
```bash
59+
source venv/bin/activate
60+
```
61+
- On **Windows (CMD)**:
62+
```cmd
63+
venv\Scripts\activate
64+
```
65+
- On **Windows (PowerShell)**:
66+
```powershell
67+
.\venv\Scripts\Activate
68+
```
69+
70+
### 2. Install Dependencies
71+
Install the required Python packages using `requirements.txt`:
72+
```bash
73+
pip install -r requirements.txt
74+
```
75+
76+
### 3. Run the Application
77+
Start the Flask application:
78+
```bash
79+
python app.py
80+
```
81+
82+
83+
### 4. Access the Application
84+
Open your web browser and go to:
85+
```
86+
http://127.0.0.1:5000
87+
```
88+
89+
---
90+
91+
## Tags
92+
`Flask` `Sorting Algorithms` `Data Visualization` `Algorithm Comparison` `Python` `Bar Graph` `Line Graph` `Random Arrays`
93+
94+
---
95+
96+
## License
97+
This project is licensed under the [MIT License](LICENSE).
98+
```
99+
100+
You can copy and paste this directly into your README file. Let me know if you need further adjustments!

__init__.py

Whitespace-only changes.

algorithms.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
def merge_sort(arr):
2+
if len(arr) > 1:
3+
mid = len(arr) // 2
4+
left_half = arr[:mid]
5+
right_half = arr[mid:]
6+
7+
merge_sort(left_half)
8+
merge_sort(right_half)
9+
10+
i = j = k = 0
11+
12+
while i < len(left_half) and j < len(right_half):
13+
if int(left_half[i]) < int(right_half[j]):
14+
arr[k] = left_half[i]
15+
i += 1
16+
else:
17+
arr[k] = right_half[j]
18+
j += 1
19+
k += 1
20+
21+
while i < len(left_half):
22+
arr[k] = left_half[i]
23+
i += 1
24+
k += 1
25+
26+
while j < len(right_half):
27+
arr[k] = right_half[j]
28+
j += 1
29+
k += 1
30+
31+
return arr
32+
33+
def insertion_sort(arr):
34+
for i in range(1, len(arr)):
35+
key = arr[i]
36+
j = i - 1
37+
while j >= 0 and int(key) < int(arr[j]):
38+
arr[j + 1] = arr[j]
39+
j -= 1
40+
arr[j + 1] = key
41+
return arr
42+
43+
def selection_sort(arr):
44+
for i in range(len(arr)):
45+
min_idx = i
46+
for j in range(i+1, len(arr)):
47+
if int(arr[min_idx]) > int(arr[j]):
48+
min_idx = j
49+
arr[i], arr[min_idx] = arr[min_idx], arr[i]
50+
return arr
51+
52+
def bubble_sort(arr):
53+
n = len(arr)
54+
for i in range(n):
55+
for j in range(0, n-i-1):
56+
if arr[j] > arr[j+1]:
57+
arr[j], arr[j+1] = arr[j+1], arr[j]
58+
return arr
59+
60+
61+
def quick_sort(arr):
62+
if len(arr) <= 1:
63+
return arr
64+
else:
65+
pivot = arr[len(arr) // 2]
66+
left = [x for x in arr if x < pivot]
67+
middle = [x for x in arr if x == pivot]
68+
right = [x for x in arr if x > pivot]
69+
return quick_sort(left) + middle + quick_sort(right)

app.py

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
from flask import Flask, render_template,request,flash,redirect,url_for,send_file
2+
from algorithms import *
3+
import time
4+
import matplotlib
5+
import io
6+
import base64
7+
from random_array import generate_random_array
8+
import matplotlib.pyplot
9+
from io import BytesIO
10+
11+
matplotlib.use('agg') # Use the 'agg' backend (non-interactive) for Matplotlib
12+
13+
#selection sort, insertion sort, and merge sort
14+
15+
app = Flask(__name__)
16+
app.secret_key = 'sort_and_sort' # Required for flash messages
17+
18+
19+
# Function to measure execution time
20+
def measure_execution_time(algorithm, arr, iterations=10):
21+
total_time = 0
22+
for _ in range(iterations):
23+
arr_copy = arr.copy()
24+
start_time = time.perf_counter()
25+
sorted_arr=algorithm(arr_copy)
26+
end_time = time.perf_counter()
27+
total_time += end_time - start_time
28+
return (total_time / iterations),sorted_arr
29+
30+
@app.route('/download-text', methods=['POST'])
31+
def download_retrieved_text():
32+
retrieved_text = request.form['results']
33+
return send_file(BytesIO(retrieved_text.encode()), as_attachment=True, download_name='results.txt', mimetype='text/plain')
34+
35+
36+
# Plot function
37+
def plot_line_graph(input_sizes, execution_times, title):
38+
# Plot function
39+
fig, ax = matplotlib.pyplot.subplots(figsize=(10, 8))
40+
for alg_name, times in execution_times.items():
41+
ax.plot(input_sizes, times, label=alg_name, marker='o')
42+
ax.set_xlabel('Input Size')
43+
ax.set_ylabel('Execution Time (seconds)')
44+
ax.set_title(title)
45+
ax.legend()
46+
ax.grid(True)
47+
48+
buf = io.BytesIO()
49+
matplotlib.pyplot.savefig(buf, format='png')
50+
buf.seek(0)
51+
plot_url = base64.b64encode(buf.getvalue()).decode('utf8')
52+
matplotlib.pyplot.close(fig)
53+
return plot_url
54+
55+
def plot_bar_graph(execution_times):
56+
# Plot the execution times
57+
fig, ax = matplotlib.pyplot.subplots(figsize=(10, 8))
58+
ax.bar(execution_times.keys(), execution_times.values(), width=0.4)
59+
ax.set_title("Execution Time Comparison")
60+
ax.set_xlabel("Algorithm")
61+
ax.set_ylabel("Execution Time (seconds)")
62+
matplotlib.pyplot.xticks(rotation=45, ha='right') # Rotate x-axis labels for better readability
63+
64+
# Save the plot to a bytes buffer
65+
buf = io.BytesIO()
66+
matplotlib.pyplot.savefig(buf, format='png')
67+
buf.seek(0)
68+
plot_url = base64.b64encode(buf.getvalue()).decode('utf8')
69+
matplotlib.pyplot.close(fig)
70+
return plot_url
71+
72+
@app.route('/view-results', methods=['POST'])
73+
def view_results():
74+
results = request.form.get('results')
75+
return render_template('view_results.html', results=results)
76+
77+
78+
# Route for home page
79+
@app.route('/', methods=['GET', 'POST'])
80+
def home():
81+
if request.method == 'POST':
82+
iterations=1
83+
input_array_sizes=None
84+
input_array = None
85+
#validations
86+
execution_type = request.form.get('execution_type')
87+
88+
if execution_type=='array':
89+
if 'array' in request.form and request.form['array']:
90+
input_array = list(map(int, request.form['array'].split(',')))
91+
provided_input="array provided : "+str(input_array)
92+
elif 'array_size' in request.form and request.form['array_size']:
93+
size=(int(request.form['array_size']))
94+
input_array= generate_random_array(size)
95+
provided_input=f"random array generated of length : {len(input_array)}"
96+
elif 'file' in request.files and request.files['file']:
97+
file = request.files['file']
98+
file_content = file.read().decode('utf-8')
99+
input_array = list(map(int, file_content.strip().split(',')))
100+
provided_input=f"file uploaded containing array of length : {len(input_array)}"
101+
else:
102+
flash("Please provide an input array or upload a file or choose array_sizes",'danger')
103+
return redirect(url_for('home'))
104+
if execution_type=='comparison':#validation for input arrays
105+
if 'input_array_sizes' in request.form and request.form['input_array_sizes']:
106+
input_array_sizes = list(map(int, request.form['input_array_sizes'].split(',')))
107+
input_array_sizes=sorted(input_array_sizes)
108+
provided_input="multiple random generated array of sizes "+str(input_array_sizes)
109+
else:
110+
flash('Please fill the input sizes', 'danger')
111+
return redirect(url_for('home'))
112+
113+
if 'iterations' in request.form and request.form['iterations']:
114+
iterations=(int(request.form['iterations']))
115+
116+
selected_algorithms = request.form.getlist('algorithms')
117+
118+
algorithms = {
119+
'merge_sort': merge_sort,
120+
'insertion_sort': insertion_sort,
121+
'selection_sort': selection_sort,
122+
'bubble_sort': bubble_sort,
123+
'quick_sort': quick_sort
124+
}
125+
# Define input sizes
126+
127+
execution_times = {}
128+
algorithms_selected={}
129+
for name in selected_algorithms:
130+
algorithms_selected[name] = algorithms[name]
131+
results=""
132+
if input_array is not None:
133+
results+=f"\n______________________________input array______________________________\n{input_array}\n"
134+
for alg_name,alg_func in algorithms_selected.items():
135+
avg_time,sorted_arr = measure_execution_time(alg_func, input_array,iterations)
136+
execution_times[alg_name] = avg_time
137+
results+=f"\n**************** {alg_name} - execution time :{avg_time} *******************\n{sorted_arr}\n"
138+
plot_url=plot_bar_graph(execution_times)
139+
elif input_array_sizes is not None:
140+
execution_times = {alg_name: [] for alg_name in algorithms_selected.keys()}
141+
for size in input_array_sizes:
142+
generated_array = generate_random_array(size)
143+
results+=f"\n______________________________Generated Array Of Size : {size}______________________________\n{generated_array}\n"
144+
for alg_name, alg_func in algorithms_selected.items():
145+
avg_time,sorted_arr = measure_execution_time(alg_func, generated_array,iterations)
146+
execution_times[alg_name].append(avg_time)
147+
results+=f"\n**************** {alg_name} - execution time :{avg_time} *******************\n{sorted_arr}\n"
148+
results+="\n\n"
149+
# Plotting
150+
plot_url=plot_line_graph(input_array_sizes, execution_times, "Algorithm Performance vs Input Size")
151+
return render_template('result.html', plot_url=plot_url, execution_times=execution_times,results=results, input_array=provided_input,iterations=iterations)
152+
return render_template('index.html')
153+
154+
155+
156+
157+
def run_flask_app():
158+
app.run(host='0.0.0.0',debug=True,)
159+
160+
if __name__ == '__main__':
161+
run_flask_app()

random_array.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import random
2+
3+
def generate_random_array(size):
4+
return [str(random.randint(0, 10000)) for _ in range(size)]
5+
6+
array_size = 1000
7+
dummy_array = generate_random_array(array_size)
8+
9+
10+
def write_file(data, file_path):
11+
with open(file_path, 'w+') as f:
12+
f.write(','.join(data))
13+
14+
write_file(dummy_array, './static/array.txt')

requirements.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
blinker==1.8.2
2+
click==8.1.7
3+
contourpy==1.2.1
4+
cycler==0.12.1
5+
Flask==3.0.3
6+
fonttools==4.53.1
7+
itsdangerous==2.2.0
8+
Jinja2==3.1.4
9+
kiwisolver==1.4.5
10+
MarkupSafe==2.1.5
11+
matplotlib==3.9.1
12+
numpy==2.0.0
13+
packaging==24.1
14+
pillow==10.4.0
15+
pyparsing==3.1.2
16+
python-dateutil==2.9.0.post0
17+
six==1.16.0
18+
Werkzeug==3.0.3

static/array.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
5389,218,1093,5109,7025,4607,9979,3575,9614,5697,6424,2454,4778,5611,2495,5518,8880,2232,3178,3621,8156,1350,5283,5064,377,431,1959,3278,8144,6666,2405,1584,6758,8969,8538,6505,5336,3784,2081,4353,2021,628,5202,3470,9576,9834,4187,5584,9479,379,8437,2378,2559,5587,6889,1061,2578,5517,4659,1771,8624,3812,7063,2325,662,5366,4020,4953,1253,9135,854,6879,1620,1185,362,1467,2053,8600,2790,9830,2652,609,514,4615,6693,5590,5340,4178,9397,6863,6886,5625,6852,6570,7216,2334,9205,6774,5915,9377,9686,2774,4830,6286,5643,1224,4768,663,1452,9308,9893,1042,6153,5503,6031,8758,6315,3563,4045,9127,1730,9931,8190,9379,6754,1771,5937,6405,1100,7178,9014,2642,8534,1800,6856,904,8425,3263,7910,5864,8184,2771,2359,5226,3547,5676,5737,32,7438,6635,8069,3664,5465,7642,8178,5435,563,9707,4237,6413,3721,1908,7567,9407,1261,4716,9549,3287,7146,1480,7966,8011,3293,2311,9210,9243,7119,9147,2862,7873,9760,8479,9416,2236,8713,4121,3212,311,4192,7592,2122,3739,9056,1179,5,6425,3837,6166,7463,6434,5009,7713,8750,6331,9053,1011,6434,4913,6461,2268,4869,8716,5060,5284,5372,2874,9958,8278,786,9566,7593,9122,7129,9035,7487,8439,3643,8275,6185,5103,6330,4938,5161,2945,4615,9594,7206,1743,6356,3869,6714,9522,8200,9234,2633,8573,5455,2799,2803,6164,8895,298,6990,8331,6099,3476,4219,2537,3195,7385,5707,8864,3194,8455,4369,9942,6205,4128,1823,7369,6376,4490,5457,9671,2592,5416,3139,6576,5823,3198,5948,1507,9250,9703,601,3774,7228,478,7807,5263,9022,4163,9567,6012,4964,9313,9666,9959,6734,4227,2311,6300,4422,2941,9731,1723,7232,1591,2958,3435,8698,1061,9821,8717,5631,8709,6479,9588,2583,1642,7972,352,9626,45,7608,3452,6225,404,3270,7082,5965,1450,2718,2730,1646,1238,5107,1771,2772,5694,2249,210,7866,5873,6893,1851,5342,1745,6662,1000,8327,220,9971,5851,2662,5454,8473,1891,4673,3709,751,257,7996,2730,8704,6466,4431,4119,6980,9321,5442,8458,4371,6889,9242,3296,330,6281,6690,8543,3998,2669,5058,7974,1395,6941,3044,7604,2886,7349,2463,7423,9935,2298,2215,8401,2430,833,1368,1636,3495,3051,6019,985,4367,5257,4186,3941,7991,36,2138,5,5060,1442,1064,8570,950,7620,1231,5759,3161,8825,5520,852,1896,9207,8722,8293,1835,4834,3149,5132,9198,5445,1463,5794,4085,0,1097,9845,2875,1572,8369,2186,5499,5378,4422,7876,3779,9150,3743,3916,5594,2140,8627,4986,9592,3358,6352,9158,222,4216,1690,1286,3248,6673,3013,1869,5859,2239,5308,7129,208,7864,5666,2684,380,899,94,250,7329,2588,7007,1605,5566,5465,8297,6905,3280,1069,5927,318,1352,9154,5774,7778,4375,1583,9654,3454,9124,3059,7790,560,596,7553,5019,914,1391,5475,6200,8103,5675,1908,5254,9116,3230,9032,1847,9763,5595,2480,7442,2542,3935,6855,5658,800,3610,5558,9326,3085,6954,225,3120,6549,2361,7489,9752,8236,1281,564,6607,3420,6558,9188,1616,1679,7925,7573,1790,5560,4919,3098,109,2346,3043,7779,2602,7480,7781,216,4548,2391,6026,2032,273,4498,7775,3375,6124,2281,7403,5069,7342,9045,7330,8007,9301,6907,1006,7229,2614,8346,7734,3350,526,6112,1898,2743,6529,5894,5463,7339,5532,9505,7667,626,6399,2230,9326,8870,3560,9631,5310,9365,824,5446,2294,1001,6836,2540,3552,8403,5881,4482,451,1213,1158,6081,7248,9690,8542,5106,1777,6667,5813,1209,1627,5828,6407,2937,5908,4070,6167,7584,8552,8335,749,2400,9694,6440,2155,1951,3452,9937,2821,4404,4450,591,8563,5302,6438,7212,7275,9774,7486,9235,8732,7624,7102,7526,193,8262,1645,8335,4811,6500,9584,4205,9688,3542,4195,7975,7094,1,4914,1212,2425,6318,9447,8419,9739,2966,1181,4769,8349,143,9102,7240,9877,61,9095,8554,992,1322,9297,8087,9903,8957,3028,6373,8312,2480,3780,6657,2202,8514,8762,817,9041,8009,8982,4064,869,6611,8115,1620,7387,5135,3767,4458,3639,1742,7415,9278,6775,6203,9100,785,801,2210,5892,1842,352,3474,7956,8794,9761,627,9937,9282,6228,6061,7425,3109,9121,5208,9958,5660,2951,7325,5589,9729,7823,9268,9255,1829,9566,6080,4414,9331,956,4037,9102,3944,8171,6288,4363,561,3561,7393,1756,7765,8564,1795,3946,5692,8457,439,2630,7623,5550,7349,3342,3751,3566,3187,3945,8334,7400,5307,2271,2321,4286,8729,6480,9429,9876,4868,2421,371,7799,4608,584,2547,5882,2326,1903,242,276,8082,1084,3391,7647,345,4558,4848,9792,7264,1214,6012,8761,848,4592,6768,4073,7197,4904,3355,5974,3371,6279,7224,6217,3773,8889,4777,2116,1275,7040,6080,7869,6175,357,9779,2087,4600,6151,4586,58,2300,9696,569,7196,5792,7655,5310,5931,1418,7729,6640,2835,6629,2543,6649,4472,6099,610,1797,9690,905,927,1668,3318,8520,8170,5053,2279,277,4769,2075,5337,9238,6503,9146,282,9651,7341,9647,109,5586,7133,657,3491,6185,7095,2810,7283,5265,4306,8710,147,3793,3039,2248,6817,8443,5871,8664,646,4688,7953,9172,8990,7411,6049,4602,7001,3147,4594,2584,604,8378,330,5540,4848,765,2594,2110,8044,7570,5799,5810,5917,6413,1899,2169,1226,7914,1891,9745,4752,7850,7546,5594,7360,6535,5813,1084,4192,2894,7122,3688,9746,4730,2986,2435,4260,5202,8557,4784,169,3066,5629,3606,2274,1292,5737,6963,4235,469,4315,484,2900,421,9533,9939,3934,7837,3017,2744,344,9696,3014,6555,5967,1132,4753,4614,8040,5148,5308,1398,6667,4073,6553,8815,1794,3070

static/chrome_qAwYb1e1p2.png

66.3 KB
Loading

static/execution_time_comparison.png

31.6 KB
Loading

static/sort_algorithm_visulizer.png

22.4 KB
Loading

0 commit comments

Comments
 (0)