Spaces:
Configuration error
Configuration error
Commit
·
8b76633
1
Parent(s):
f516ff6
Initial commit
Browse files- README.md +26 -0
- algorithms.py +44 -3
- app.py +115 -81
- requirements.txt +1 -0
README.md
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Sorting Algorithm Visualizer
|
| 2 |
+
|
| 3 |
+
A Streamlit-based application that visually compares **Insertion Sort** and **Merge Sort** step by step.
|
| 4 |
+
|
| 5 |
+

|
| 6 |
+
|
| 7 |
+
## Features
|
| 8 |
+
|
| 9 |
+
- Generates a random list of integers
|
| 10 |
+
- Runs Insertion Sort and Merge Sort side by side
|
| 11 |
+
- Step-by-step animated visualization using Plotly
|
| 12 |
+
- Highlights active comparisons and sorted segments
|
| 13 |
+
- Displays total number of steps for each algorithm
|
| 14 |
+
- Brief description of algorithm logic
|
| 15 |
+
|
| 16 |
+
## Technologies Used
|
| 17 |
+
|
| 18 |
+
- Python 3
|
| 19 |
+
- Streamlit
|
| 20 |
+
- Plotly
|
| 21 |
+
|
| 22 |
+
## How to Run
|
| 23 |
+
|
| 24 |
+
```bash
|
| 25 |
+
pip install -r requirements.txt
|
| 26 |
+
streamlit run app.py
|
algorithms.py
CHANGED
|
@@ -1,6 +1,3 @@
|
|
| 1 |
-
# insertion sort
|
| 2 |
-
|
| 3 |
-
|
| 4 |
def insertion_sort(arr):
|
| 5 |
steps = [] # keep all steps here
|
| 6 |
a = arr.copy()
|
|
@@ -20,3 +17,47 @@ def insertion_sort(arr):
|
|
| 20 |
{"array": a.copy(), "active_index": j + 1, "sorted_boundary": i}
|
| 21 |
) # save every moment
|
| 22 |
return steps
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
def insertion_sort(arr):
|
| 2 |
steps = [] # keep all steps here
|
| 3 |
a = arr.copy()
|
|
|
|
| 17 |
{"array": a.copy(), "active_index": j + 1, "sorted_boundary": i}
|
| 18 |
) # save every moment
|
| 19 |
return steps
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
def merge_sort(arr):
|
| 23 |
+
steps = []
|
| 24 |
+
a = arr.copy()
|
| 25 |
+
merge_sort_recursive(a, 0, len(a) - 1, steps)
|
| 26 |
+
return steps
|
| 27 |
+
|
| 28 |
+
def merge_sort_recursive(arr,left,right,steps):
|
| 29 |
+
if left < right:
|
| 30 |
+
mid = (left + right) // 2
|
| 31 |
+
merge_sort_recursive(arr, left, mid, steps)
|
| 32 |
+
merge_sort_recursive(arr, mid + 1, right, steps)
|
| 33 |
+
merge(arr, left, mid, right, steps)
|
| 34 |
+
|
| 35 |
+
def merge(arr, left, mid, right, steps):
|
| 36 |
+
left_part = arr[left:mid+1]
|
| 37 |
+
right_part = arr[mid + 1:right+1]
|
| 38 |
+
|
| 39 |
+
i = j = 0
|
| 40 |
+
k = left
|
| 41 |
+
|
| 42 |
+
while i < len(left_part) and j < len(right_part):
|
| 43 |
+
if left_part[i] <= right_part[j]:
|
| 44 |
+
arr[k] = left_part[i]
|
| 45 |
+
steps.append({"array": arr.copy(), "active_index":k, "sorted_boundary": right})
|
| 46 |
+
i += 1
|
| 47 |
+
else:
|
| 48 |
+
arr[k] = right_part[j]
|
| 49 |
+
steps.append({"array": arr.copy(), "active_index":k, "sorted_boundary": right})
|
| 50 |
+
j += 1
|
| 51 |
+
k += 1
|
| 52 |
+
|
| 53 |
+
while i < len(left_part):
|
| 54 |
+
arr[k] = left_part[i]
|
| 55 |
+
steps.append({"array": arr.copy(), "active_index":k, "sorted_boundary": right})
|
| 56 |
+
i += 1
|
| 57 |
+
k += 1
|
| 58 |
+
|
| 59 |
+
while j < len(right_part):
|
| 60 |
+
arr[k] = right_part[j]
|
| 61 |
+
steps.append({"array": arr.copy(), "active_index":k, "sorted_boundary": right})
|
| 62 |
+
j += 1
|
| 63 |
+
k += 1
|
app.py
CHANGED
|
@@ -2,89 +2,123 @@ import random
|
|
| 2 |
import plotly.graph_objects as go
|
| 3 |
import matplotlib.pyplot as plt
|
| 4 |
import streamlit as st
|
|
|
|
| 5 |
|
| 6 |
-
from algorithms import insertion_sort
|
| 7 |
-
|
| 8 |
-
st.title("Insertion Sort Visualizer")
|
| 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 |
data=[go.Scatter(
|
| 42 |
-
x=list(range(len(array))),
|
| 43 |
-
y=array,
|
| 44 |
mode="markers+text",
|
| 45 |
-
marker=dict(size=40, color=
|
| 46 |
-
text=array,
|
| 47 |
textposition="middle center"
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
import plotly.graph_objects as go
|
| 3 |
import matplotlib.pyplot as plt
|
| 4 |
import streamlit as st
|
| 5 |
+
import time
|
| 6 |
|
| 7 |
+
from algorithms import insertion_sort, merge_sort
|
| 8 |
+
|
| 9 |
+
st.title("Insertion Sort vs Merge Sort Visualizer")
|
| 10 |
+
|
| 11 |
+
# --- Veri Girişi ---
|
| 12 |
+
st.subheader("Input Configuration")
|
| 13 |
+
length = st.slider("List length", 5, 20, 8)
|
| 14 |
+
data = random.sample(range(1, 30), length)
|
| 15 |
+
st.write(f"Input array: {data}")
|
| 16 |
+
|
| 17 |
+
if st.button("Compare Insertion Sort vs Merge Sort"):
|
| 18 |
+
data_insertion = data.copy()
|
| 19 |
+
data_merge = data.copy()
|
| 20 |
+
|
| 21 |
+
# Insertion Sort
|
| 22 |
+
steps_insertion = insertion_sort(data_insertion)
|
| 23 |
+
|
| 24 |
+
# Merge Sort
|
| 25 |
+
steps_merge = merge_sort(data_merge)
|
| 26 |
+
|
| 27 |
+
st.subheader("Comparison Results")
|
| 28 |
+
col1, col2 = st.columns(2)
|
| 29 |
+
|
| 30 |
+
with col1:
|
| 31 |
+
st.markdown("### Insertion Sort")
|
| 32 |
+
st.write(f"Total steps: {len(steps_insertion)}")
|
| 33 |
+
|
| 34 |
+
with col2:
|
| 35 |
+
st.markdown("### Merge Sort")
|
| 36 |
+
st.write(f"Total steps: {len(steps_merge)}")
|
| 37 |
+
|
| 38 |
+
# --- Görsel Karşılaştırma ---
|
| 39 |
+
st.subheader("Visual Comparison")
|
| 40 |
+
col1, col2 = st.columns(2)
|
| 41 |
+
|
| 42 |
+
def create_animation(steps, title, color_fn):
|
| 43 |
+
frames = []
|
| 44 |
+
for i, step in enumerate(steps):
|
| 45 |
+
array = step["array"]
|
| 46 |
+
active_index = step.get("active_index", -1)
|
| 47 |
+
sorted_boundary = step.get("sorted_boundary", -1)
|
| 48 |
+
|
| 49 |
+
colors = color_fn(len(array), active_index, sorted_boundary)
|
| 50 |
+
|
| 51 |
+
frames.append(go.Frame(
|
| 52 |
+
data=[go.Scatter(
|
| 53 |
+
x=list(range(len(array))),
|
| 54 |
+
y=array,
|
| 55 |
+
mode="markers+text",
|
| 56 |
+
marker=dict(size=40, color=colors),
|
| 57 |
+
text=array,
|
| 58 |
+
textposition="middle center"
|
| 59 |
+
)],
|
| 60 |
+
name=f"Step {i+1}"
|
| 61 |
+
))
|
| 62 |
+
|
| 63 |
+
initial = steps[0]
|
| 64 |
+
initial_colors = color_fn(len(initial["array"]),
|
| 65 |
+
initial.get("active_index", -1),
|
| 66 |
+
initial.get("sorted_boundary", -1))
|
| 67 |
+
|
| 68 |
+
fig = go.Figure(
|
| 69 |
data=[go.Scatter(
|
| 70 |
+
x=list(range(len(initial["array"]))),
|
| 71 |
+
y=initial["array"],
|
| 72 |
mode="markers+text",
|
| 73 |
+
marker=dict(size=40, color=initial_colors),
|
| 74 |
+
text=initial["array"],
|
| 75 |
textposition="middle center"
|
| 76 |
)],
|
| 77 |
+
layout=go.Layout(
|
| 78 |
+
title=title,
|
| 79 |
+
xaxis=dict(range=[-0.5, len(initial["array"]) - 0.5]),
|
| 80 |
+
yaxis=dict(range=[0, max(max(s['array']) for s in steps) + 5]),
|
| 81 |
+
updatemenus=[dict(
|
| 82 |
+
type="buttons",
|
| 83 |
+
buttons=[dict(label="Play", method="animate", args=[None])],
|
| 84 |
+
showactive=False
|
| 85 |
+
)],
|
| 86 |
+
sliders=[{
|
| 87 |
+
"steps": [{
|
| 88 |
+
"args": [[f"Step {i+1}"], {"frame": {"duration": 500, "redraw": True}}],
|
| 89 |
+
"label": f"{i+1}",
|
| 90 |
+
"method": "animate"
|
| 91 |
+
} for i in range(len(frames))],
|
| 92 |
+
"transition": {"duration": 0},
|
| 93 |
+
"x": 0, "y": -0.1,
|
| 94 |
+
"currentvalue": {"prefix": "Step: "}
|
| 95 |
+
}]
|
| 96 |
+
),
|
| 97 |
+
frames=frames
|
| 98 |
+
)
|
| 99 |
+
return fig
|
| 100 |
+
|
| 101 |
+
def insertion_colors(length, active_index, sorted_boundary):
|
| 102 |
+
return [
|
| 103 |
+
"red" if j == active_index else
|
| 104 |
+
"green" if j <= sorted_boundary else "gray"
|
| 105 |
+
for j in range(length)
|
| 106 |
+
]
|
| 107 |
+
|
| 108 |
+
def merge_colors(length, active_index, sorted_boundary):
|
| 109 |
+
return [
|
| 110 |
+
"purple" if j == active_index else
|
| 111 |
+
"blue" if j <= sorted_boundary else "gray"
|
| 112 |
+
for j in range(length)
|
| 113 |
+
]
|
| 114 |
+
|
| 115 |
+
with col1:
|
| 116 |
+
st.plotly_chart(create_animation(steps_insertion, "Insertion Sort", insertion_colors))
|
| 117 |
+
|
| 118 |
+
with col2:
|
| 119 |
+
st.plotly_chart(create_animation(steps_merge, "Merge Sort", merge_colors))
|
| 120 |
+
|
| 121 |
+
# --- Açıklamalar ---
|
| 122 |
+
st.subheader("About the Algorithms")
|
| 123 |
+
st.markdown("**Insertion Sort:** A simple comparison-based algorithm that builds the sorted list one element at a time. Best for small or nearly sorted datasets. Time complexity: O(n²).")
|
| 124 |
+
st.markdown("**Merge Sort:** A divide-and-conquer algorithm that recursively splits the list and merges them in sorted order. Efficient for large datasets. Time complexity: O(n log n).")
|
requirements.txt
CHANGED
|
@@ -27,6 +27,7 @@ pandas==2.3.1
|
|
| 27 |
pathspec==0.12.1
|
| 28 |
pillow==11.3.0
|
| 29 |
platformdirs==4.3.8
|
|
|
|
| 30 |
protobuf==6.31.1
|
| 31 |
pyarrow==21.0.0
|
| 32 |
pydeck==0.9.1
|
|
|
|
| 27 |
pathspec==0.12.1
|
| 28 |
pillow==11.3.0
|
| 29 |
platformdirs==4.3.8
|
| 30 |
+
plotly==6.2.0
|
| 31 |
protobuf==6.31.1
|
| 32 |
pyarrow==21.0.0
|
| 33 |
pydeck==0.9.1
|