├── README.md
├── assets
├── bubble-sort.js
├── favicon.ico
├── heapsort.js
├── insertion-sort.js
├── merge-sort.js
├── quicksort.js
├── script.js
├── selection-sort.js
└── style.css
└── index.html
/README.md:
--------------------------------------------------------------------------------
1 | # Sorting Visualizer
2 |
3 | **A static website for visualizing different comparison based sorting algorithms.**
4 |
5 | [Website Link](https://mahfuzrifat7.github.io/SortingVisualizer "Sorting Visualizer")
--------------------------------------------------------------------------------
/assets/bubble-sort.js:
--------------------------------------------------------------------------------
1 | async function bubbleSort() {
2 | var i, j;
3 | await sleep(delay);
4 |
5 | for(i = 0; i < size - 1; i++) {
6 | for(j = 0; j < size - i - 1; j++) {
7 | await sleep(delay);
8 |
9 | setColor(j, COMPARE);
10 | setColor(j + 1, COMPARE);
11 | await sleep(delay);
12 |
13 | if(arr[j] > arr[j + 1]) {
14 | swap(j, j + 1);
15 | await sleep(delay);
16 | }
17 |
18 | setColor(j, UNSORTED);
19 | setColor(j + 1, UNSORTED);
20 | }
21 |
22 | await sleep(delay);
23 |
24 | setColor(j, SORTED);
25 | }
26 |
27 | setColor(0, SORTED);
28 | }
29 |
--------------------------------------------------------------------------------
/assets/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mahfuzrifat7/SortingVisualizer/605efa880cdf978c182876bef97f74c27c5f1450/assets/favicon.ico
--------------------------------------------------------------------------------
/assets/heapsort.js:
--------------------------------------------------------------------------------
1 | var heapSize;
2 |
3 | function left(i) {
4 | return 2 * i + 1;
5 | }
6 |
7 | function right(i) {
8 | return 2 * i + 2;
9 | }
10 |
11 | async function maxHeapify(i) {
12 | var l = left(i);
13 | var r = right(i);
14 | var largest, temp;
15 |
16 | setColor(i, COMPARE);
17 | if(l < heapSize)
18 | setColor(l, LEFT);
19 | if(r < heapSize)
20 | setColor(r, RIGHT);
21 |
22 | await sleep(delay);
23 |
24 | if(l < heapSize && arr[l] > arr[i])
25 | largest = l;
26 | else
27 | largest = i;
28 |
29 | if(r < heapSize && arr[r] > arr[largest])
30 | largest = r;
31 |
32 | if(l < heapSize)
33 | setColor(l, UNSORTED);
34 | if(r < heapSize)
35 | setColor(r, UNSORTED);
36 | setColor(largest, SELECTED);
37 |
38 | await sleep(delay);
39 |
40 | if(largest != i) {
41 | swap(i, largest);
42 | setColor(largest, COMPARE);
43 | setColor(i, SELECTED);
44 | await sleep(delay);
45 |
46 | setColor(largest, UNSORTED);
47 | setColor(i, UNSORTED);
48 |
49 | await maxHeapify(largest);
50 | }
51 | else
52 | setColor(i, UNSORTED);
53 | }
54 |
55 | async function buildMaxHeap() {
56 | heapSize = size;
57 |
58 | for(var i = Math.floor(size / 2) - 1; i >= 0; i--)
59 | await maxHeapify(i);
60 | }
61 |
62 | async function heapsort() {
63 | await sleep(delay);
64 |
65 | await buildMaxHeap();
66 |
67 | for(var i = size - 1; i > 0; i--) {
68 | setColor(0, SELECTED);
69 | setColor(i, COMPARE);
70 | await sleep(delay);
71 |
72 | setColor(0, COMPARE);
73 | setColor(i, SELECTED);
74 | swap(0, i);
75 | heapSize--;
76 | await sleep(delay);
77 |
78 | setColor(i, SORTED);
79 |
80 | await maxHeapify(0);
81 | }
82 |
83 | setColor(0, SORTED);
84 | }
85 |
--------------------------------------------------------------------------------
/assets/insertion-sort.js:
--------------------------------------------------------------------------------
1 | async function insertionSort() {
2 | var i, j, key;
3 | await sleep(delay);
4 |
5 | setColor(0, SELECTED);
6 | await sleep(delay);
7 |
8 | setColor(0, SORTED);
9 |
10 | for(i = 1; i < size; i++) {
11 | await sleep(delay);
12 |
13 | setColor(i, SELECTED);
14 | await sleep(delay);
15 |
16 | j = i - 1;
17 | key = arr[i];
18 |
19 | while(j >= 0 && arr[j] > key) {
20 | setColor(j, COMPARE);
21 | await sleep(delay);
22 |
23 | swap(j, j + 1);
24 | setColor(j, SELECTED);
25 | setColor(j + 1, COMPARE);
26 | await sleep(delay);
27 |
28 | setColor(j + 1, SORTED);
29 | await sleep(delay);
30 |
31 | j--;
32 | }
33 |
34 | setColor(j + 1, SORTED);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/assets/merge-sort.js:
--------------------------------------------------------------------------------
1 | async function merge(p, q, r) {
2 | await sleep(delay);
3 |
4 | var i, j;
5 | var n1 = q - p + 1;
6 | var n2 = r - q;
7 | var L = [];
8 | var R = [];
9 |
10 | for(i = 0; i < n1; i++) {
11 | L.push(arr[p + i]);
12 | setColor(p + i, LEFT);
13 | }
14 | for(j = 0; j < n2; j++) {
15 | R.push(arr[q + j + 1]);
16 | setColor(q + j + 1, RIGHT);
17 | }
18 |
19 | L.push(Infinity);
20 | R.push(Infinity);
21 |
22 | i = 0;
23 | j = 0;
24 |
25 | for(var k = p; k <= r; k++) {
26 | await sleep(delay);
27 |
28 | if(L[i] <= R[j]) {
29 | arr[k] = L[i];
30 | i++;
31 | }
32 | else {
33 | arr[k] = R[j];
34 | j++;
35 | }
36 |
37 | setHeight(k, arr[k]);
38 | setColor(k, SELECTED);
39 | }
40 |
41 | await sleep(delay);
42 |
43 | if(p == 0 && r == size - 1)
44 | setColorRange(p, r, SORTED);
45 | else
46 | setColorRange(p, r, UNSORTED);
47 | }
48 |
49 | async function mergeSort(p, r) {
50 | if(p < r) {
51 | var q = Math.floor( (p + r) / 2 );
52 |
53 | await mergeSort(p, q);
54 |
55 | await mergeSort(q + 1, r);
56 |
57 | await merge(p, q, r);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/assets/quicksort.js:
--------------------------------------------------------------------------------
1 | async function partition(p, r) {
2 | await sleep(delay);
3 |
4 | var i = p - 1;
5 | setColor(r, SELECTED);
6 |
7 | for(var j = p; j < r; j++) {
8 | await sleep(delay);
9 |
10 | if(arr[j] <= arr[r]) {
11 | i++;
12 | swap(i, j);
13 | setColor(j, RIGHT);
14 | setColor(i, LEFT);
15 | }
16 | else
17 | setColor(j, RIGHT);
18 | }
19 |
20 | if(i + 1 < r) {
21 | await sleep(delay);
22 |
23 | swap(i + 1, r);
24 | setColor(r, RIGHT);
25 | setColor(i + 1, SELECTED);
26 | }
27 |
28 | await sleep(delay);
29 |
30 | setColorRange(p, r, UNSORTED);
31 |
32 | return i + 1;
33 | }
34 |
35 | async function quicksort(p, r) {
36 | if(p < r) {
37 | var q = await partition(p, r);
38 |
39 | await quicksort(p, q - 1);
40 |
41 | setColorRange(p, q, SORTED);
42 | await quicksort(q + 1, r);
43 |
44 | setColorRange(q + 1, r, SORTED);
45 | }
46 |
47 | if(p == 0 && r == size - 1)
48 | await sleep(delay);
49 | }
50 |
--------------------------------------------------------------------------------
/assets/script.js:
--------------------------------------------------------------------------------
1 | const MIN_SIZE = 4;
2 | const MAX_SIZE = 64;
3 | const DEFAULT_SIZE = 32;
4 |
5 | const MIN_SPEED = 1;
6 | const MAX_SPEED = 4;
7 | const DEFAULT_SPEED = 3;
8 |
9 | const MIN = 20;
10 | const MAX = 300;
11 |
12 | const WAITING_TIME = 100;
13 |
14 | const UNSORTED = 'deepskyblue';
15 | const SORTED = 'mediumspringgreen';
16 | const COMPARE = 'crimson';
17 | const SELECTED = 'blueviolet';
18 | const LEFT = 'gold';
19 | const RIGHT = 'orangered';
20 |
21 | var size;
22 | var delay;
23 |
24 | var arr = [];
25 |
26 | var array_container_width;
27 | var element_width;
28 | var element_width_max;
29 | var margin_element;
30 |
31 | var algo_selected;
32 |
33 | function updateValues() {
34 | array_container_width = Math.floor( $("#array-container").width() );
35 | element_width_max = Math.floor(array_container_width / 20);
36 |
37 | margin_element = 2;
38 | if( parseInt( $(window).width() ) < 1200 )
39 | margin_element = 1;
40 | }
41 |
42 | function findElementWidth() {
43 | element_width = Math.floor(array_container_width / size);
44 | element_width -= 2 * margin_element;
45 |
46 | if(element_width > element_width_max)
47 | element_width = element_width_max;
48 | }
49 |
50 | function createArray() {
51 | arr = [];
52 | $("#array").html('');
53 |
54 | for(var i = 0; i < size; i++) {
55 | var n = Math.floor( Math.random() * (MAX - MIN + 1) ) + MIN;
56 | arr.push(n);
57 |
58 | var $element = $('
');
59 | $element.attr('id', "e" + i);
60 | $element.attr('class', "element");
61 | $element.css('background-color', UNSORTED);
62 | $element.css('width', element_width.toString() + 'px');
63 | $element.css('height', n.toString() + 'px');
64 | $element.css('margin-left', margin_element + 'px');
65 | $element.css('margin-right', margin_element + 'px');
66 | $element.appendTo("#array");
67 | }
68 | }
69 |
70 | function setHeight(id, height) {
71 | $("#e" + id).css('height', height);
72 | }
73 |
74 | function setColor(id, color) {
75 | $("#e" + id).css('background-color', color);
76 | }
77 |
78 | function setColorRange(p, r, color) {
79 | for(var i = p; i <= r; i++)
80 | $("#e" + i).css('background-color', color);
81 | }
82 |
83 | function swap(a, b) {
84 | var temp = arr[a];
85 | arr[a] = arr[b];
86 | arr[b] = temp;
87 |
88 | var h1 = $("#e" + a).css('height');
89 | var h2 = $("#e" + b).css('height');
90 |
91 | setHeight(a, h2);
92 | setHeight(b, h1);
93 | }
94 |
95 | function disableOthers() {
96 | $("#sort").prop('disabled', true);
97 | $("#randomize").prop('disabled', true);
98 | $("#size-slider").prop('disabled', true);
99 | }
100 |
101 | function enableOthers() {
102 | $("#sort").prop('disabled', false);
103 | $("#randomize").prop('disabled', false);
104 | $("#size-slider").prop('disabled', false);
105 | }
106 |
107 | function sleep(ms) {
108 | return new Promise(resolve => setTimeout(resolve, ms));
109 | }
110 |
111 | $(document).ready(function() {
112 | $("#size-slider").attr('min', MIN_SIZE);
113 | $("#size-slider").attr('max', MAX_SIZE);
114 | $("#size-slider").attr('value', DEFAULT_SIZE);
115 |
116 | $("#speed-slider").attr('min', MIN_SPEED);
117 | $("#speed-slider").attr('max', MAX_SPEED);
118 | $("#speed-slider").attr('value', DEFAULT_SPEED);
119 |
120 | size = DEFAULT_SIZE;
121 | delay = WAITING_TIME * Math.pow(2, MAX_SPEED - DEFAULT_SPEED);
122 |
123 | updateValues();
124 |
125 | findElementWidth();
126 | createArray();
127 |
128 | $("#randomize").click(
129 | function() {
130 | createArray();
131 | }
132 | );
133 |
134 | $(".algo-btn").click(
135 | function() {
136 | algo_selected = $(this).html();
137 |
138 | $(".algo-btn-active").removeClass('algo-btn-active');
139 | $(this).addClass('algo-btn-active');
140 |
141 | $("#no-algo-warning").removeClass('display-flex');
142 | $("#no-algo-warning").addClass('display-none');
143 | }
144 | );
145 |
146 | $("#sort").click(
147 | async function() {
148 | disableOthers();
149 |
150 | setColorRange(0, size - 1, UNSORTED);
151 |
152 | if(algo_selected == "Bubble Sort")
153 | await bubbleSort();
154 | else if(algo_selected == "Selection Sort")
155 | await selectionSort();
156 | else if(algo_selected == "Insertion Sort")
157 | await insertionSort();
158 | else if(algo_selected == "Merge Sort")
159 | await mergeSort(0, size - 1);
160 | else if(algo_selected == "Quicksort")
161 | await quicksort(0, size - 1);
162 | else if(algo_selected == "Heapsort")
163 | await heapsort();
164 | else {
165 | $("#no-algo-warning").removeClass('display-none');
166 | $("#no-algo-warning").addClass('display-flex');
167 | }
168 |
169 | enableOthers();
170 | }
171 | );
172 |
173 | $("#size-slider").on('input', function() {
174 | size = $(this).val();
175 |
176 | findElementWidth();
177 | createArray();
178 | });
179 |
180 | $("#speed-slider").on('input', function() {
181 | delay = WAITING_TIME * Math.pow(2, MAX_SPEED - $(this).val());
182 | });
183 |
184 | $(window).resize(function() {
185 | if(array_container_width != Math.floor( $("#array-container").width() )) {
186 | updateValues();
187 |
188 | findElementWidth();
189 |
190 | for(var i = 0; i < size; i++) {
191 | $("#e" + i).css('width', element_width.toString() + 'px');
192 | $("#e" + i).css('margin-left', margin_element + 'px');
193 | $("#e" + i).css('margin-right', margin_element + 'px');
194 | }
195 | }
196 | });
197 | });
198 |
--------------------------------------------------------------------------------
/assets/selection-sort.js:
--------------------------------------------------------------------------------
1 | async function selectionSort() {
2 | var i, j, min_idx;
3 |
4 | for(i = 0; i < size - 1; i++) {
5 | await sleep(delay);
6 |
7 | min_idx = i;
8 | setColor(min_idx, SELECTED);
9 |
10 | for(j = i + 1; j < size; j++) {
11 | await sleep(delay);
12 |
13 | setColor(j, COMPARE);
14 |
15 | await sleep(delay);
16 |
17 | if(arr[j] < arr[min_idx]) {
18 | setColor(min_idx, UNSORTED);
19 | min_idx = j;
20 | setColor(min_idx, SELECTED);
21 | await sleep(delay);
22 | }
23 | else
24 | setColor(j, UNSORTED);
25 | }
26 |
27 | await sleep(delay);
28 |
29 | if(min_idx != i) {
30 | setColor(i, COMPARE);
31 | await sleep(delay);
32 |
33 | setColor(min_idx, COMPARE);
34 | setColor(i, SELECTED);
35 | swap(min_idx, i);
36 | await sleep(delay);
37 | }
38 |
39 | setColor(min_idx, UNSORTED);
40 | setColor(i, SORTED);
41 | }
42 |
43 | setColor(size - 1, SORTED);
44 | }
45 |
--------------------------------------------------------------------------------
/assets/style.css:
--------------------------------------------------------------------------------
1 | *:focus, button:focus {
2 | outline: none;
3 | }
4 |
5 | body {
6 | background-color: black;
7 | font-family: "Catamaran", sans-serif;
8 | color: #ccc;
9 | }
10 |
11 | .display-none {
12 | display: none;
13 | }
14 |
15 | .display-flex {
16 | display: flex;
17 | }
18 |
19 | #array-container {
20 | height: 350px;
21 | margin-top: 3em;
22 | display: flex;
23 | flex-direction: column-reverse;
24 | position: relative;
25 | }
26 |
27 | #array {
28 | margin: 1em auto;
29 | }
30 |
31 | .element {
32 | display: inline-block;
33 | border-radius: 5px;
34 | }
35 |
36 | #no-algo-warning {
37 | position: absolute;
38 | justify-content: center;
39 | align-items: center;
40 | top: 0;
41 | bottom: 0;
42 | left: 0;
43 | right: 0;
44 | margin: auto;
45 | width: 250px;
46 | height: 50px;
47 | text-align: center;
48 | background-color: rgba(0, 0, 0, 0.8);
49 | border: 1px solid #ccc;
50 | border-radius: 5px;
51 | }
52 |
53 | #algo-container {
54 | max-width: 1000px;
55 | margin: 1em auto;
56 | }
57 |
58 | .algo-btn, #sort, #randomize {
59 | background-color: #222;
60 | margin: 5px 2px;
61 | padding: 5px 20px;
62 | color: #ccc;
63 | font-size: 1.2em;
64 | border: none;
65 | border-radius: 50px;
66 | }
67 |
68 | .algo-btn:hover, .algo-btn-active {
69 | background-color: #ccc;
70 | color: #222;
71 | }
72 |
73 | #sort {
74 | float: right;
75 | background-color: mediumspringgreen;
76 | color: black;
77 | }
78 |
79 | #sort:hover, #randomize:hover {
80 | opacity: 0.8;
81 | }
82 |
83 | #sort:disabled, #randomize:disabled {
84 | opacity: 0.5;
85 | cursor: not-allowed;
86 | }
87 |
88 | #change-container {
89 | max-width: 500px;
90 | margin: 1em auto;
91 | }
92 |
93 | #randomize, .slider-container {
94 | vertical-align: middle;
95 | }
96 |
97 | #randomize {
98 | background-color: crimson;
99 | color: #ddd;
100 | }
101 |
102 | #sliders {
103 | float: right;
104 | }
105 |
106 | .slider-container {
107 | display: inline-block;
108 | margin-left: 20px;
109 | }
110 |
111 | .slider-container label {
112 | display: block;
113 | margin: 0;
114 | text-align: center;
115 | font-size: 1.2em;
116 | }
117 |
118 | .slider {
119 | -webkit-appearance: none;
120 | width: 130px;
121 | height: 15px;
122 | background-color: transparent;
123 | }
124 |
125 | .slider::-webkit-slider-runnable-track {
126 | -webkit-appearance: none;
127 | height: 5px;
128 | background-color: #ccc;
129 | border-radius: 5px;
130 | cursor: pointer;
131 | }
132 |
133 | .slider::-moz-range-track {
134 | height: 5px;
135 | background-color: #ccc;
136 | border-radius: 5px;
137 | cursor: pointer;
138 | }
139 |
140 | .slider::-moz-range-progress {
141 | height: 5px;
142 | background-color: #777;
143 | border-radius: 5px;
144 | cursor: pointer;
145 | }
146 |
147 | .slider::-webkit-slider-thumb {
148 | -webkit-appearance: none;
149 | background-color: #222;
150 | border: 2px solid #ccc;
151 | width: 15px;
152 | height: 15px;
153 | border-radius: 15px;
154 | margin-top: -5px;
155 | }
156 |
157 | .slider::-moz-range-thumb {
158 | background-color: #222;
159 | border: 2px solid #ccc;
160 | width: 13px;
161 | height: 13px;
162 | border-radius: 13px;
163 | cursor: pointer;
164 | }
165 |
166 | .slider:disabled {
167 | opacity: 0.5;
168 | }
169 |
170 | .slider:disabled::-webkit-slider-runnable-track {
171 | cursor: not-allowed;
172 | }
173 |
174 | .slider:disabled::-moz-range-track {
175 | cursor: not-allowed;
176 | }
177 |
178 | .slider:disabled::-moz-range-progress {
179 | cursor: not-allowed;
180 | }
181 |
182 | .slider:disabled::-moz-range-thumb {
183 | cursor: not-allowed;
184 | }
185 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
Sorting Visualizer
13 |
14 |
15 |
16 |
17 |
18 |
No Algorithm Selected!
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------