gokaymeydan commited on
Commit
8b76633
·
1 Parent(s): f516ff6

Initial commit

Browse files
Files changed (4) hide show
  1. README.md +26 -0
  2. algorithms.py +44 -3
  3. app.py +115 -81
  4. 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
+ ![Demo Animation](demo.gif)
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
- option = st.radio("Choose input method:", ["Manual Input", "Random List"])
11
-
12
- if option == "Manual Input":
13
- user_input = st.text_input("Enter numbers seperated by commas (like 5,3,1,4)")
14
- if user_input:
15
- data = list(map(int, user_input.split(",")))
16
- else:
17
- length = st.slider("List length", 5, 20, 8)
18
- data = random.sample(range(1, 30), length)
19
-
20
- if "data" in locals() and st.button("Visualize Insertion Sort"):
21
- steps = insertion_sort(data)
22
-
23
- st.write(f"Total steps: {len(steps)}")
24
-
25
- frames = []
26
- for i, step in enumerate(steps):
27
- array = step["array"]
28
- active_index = step["active_index"]
29
- sorted_boundary = step["sorted_boundary"]
30
-
31
- colors = []
32
- for j in range(len(array)):
33
- if j == active_index:
34
- colors.append("red")
35
- elif j <= sorted_boundary:
36
- colors.append("green")
37
- else:
38
- colors.append("gray")
39
-
40
- frames.append(go.Frame(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  data=[go.Scatter(
42
- x=list(range(len(array))),
43
- y=array,
44
  mode="markers+text",
45
- marker=dict(size=40, color=colors),
46
- text=array,
47
  textposition="middle center"
48
  )],
49
- name=f"Step {i+1}"
50
- ))
51
- initial = steps[0]
52
- initial_colors = [
53
- "red" if j == initial["active_index"] else
54
- "green" if j <= initial["sorted_boundary"] else "gray"
55
- for j in range(len(initial["array"]))
56
- ]
57
-
58
- fig = go.Figure(
59
- data=[go.Scatter(
60
- x=list(range(len(initial["array"]))),
61
- y=initial["array"],
62
- mode="markers+text",
63
- marker=dict(size=40, color=initial_colors),
64
- text=initial["array"],
65
- textposition="middle center"
66
- )],
67
- layout=go.Layout(
68
- title="Insertion Sort Animation",
69
- xaxis=dict(range=[-0.5, len(initial["array"]) - 0.5]),
70
- yaxis=dict(range=[0, max(max(s['array']) for s in steps) + 5]),
71
- updatemenus=[dict(
72
- type="buttons",
73
- buttons=[dict(label="Play", method="animate", args=[None])],
74
- showactive=False
75
- )],
76
- sliders=[{
77
- "steps": [{
78
- "args": [[f"Step {i+1}"], {"frame": {"duration": 500, "redraw": True}}],
79
- "label": f"{i+1}",
80
- "method": "animate"
81
- } for i in range(len(frames))],
82
- "transition": {"duration": 0},
83
- "x": 0, "y": -0.1,
84
- "currentvalue": {"prefix": "Step: "}
85
- }]
86
- ),
87
- frames=frames
88
- )
89
-
90
- st.plotly_chart(fig)
 
 
 
 
 
 
 
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