Skip to content
Snippets Groups Projects
Commit 7b3d1958 authored by Daniel Runte's avatar Daniel Runte
Browse files

Merge branch 'feature/MergeSort' into 'main'

implemented MergeSort

See merge request !3
parents 0aedb6dc daf09a14
No related branches found
No related tags found
1 merge request!3implemented MergeSort
Pipeline #224003 passed
...@@ -18,6 +18,7 @@ COPY vite.config.js . ...@@ -18,6 +18,7 @@ COPY vite.config.js .
# port 5173 # port 5173
EXPOSE 5173 EXPOSE 5173
EXPOSE 9229
#Start #Start
CMD ["npm", "run", "dev", "--", "--host"] CMD ["npm", "run", "dev", "--", "--host", "$DEBUG_FLAG"]
...@@ -4,13 +4,16 @@ services: ...@@ -4,13 +4,16 @@ services:
container_name: Sorting-Visualizer container_name: Sorting-Visualizer
ports: ports:
- 127.0.0.1:5173:5173 - 127.0.0.1:5173:5173
- 127.0.0.1:9229:9229
volumes: volumes:
- ./src/:/app/sorting-visualizer/src/ - ./src/:/app/sorting-visualizer/src/
- ./package-lock.json:/app/sorting-visualizer/package-lock.json - ./package-lock.json:/app/sorting-visualizer/package-lock.json
- ./package.json:/app/sorting-visualizer/package.json - ./package.json:/app/sorting-visualizer/package.json
networks: networks:
- my-network - my-network
environment:
DEBUG_FLAG: "--inspect=0.0.0.0:9229"
networks: networks:
my-network: my-network:
driver: bridge driver: bridge
async function MergeSort(EingangsArray, startIdx, endIdx, arrayCopy, updateBars, setColor, sortSpeed) {
if (startIdx >= endIdx) return;
// Split array
const cuttingEdge = Math.floor((startIdx + endIdx) / 2);
// Recursively sort both halves
await MergeSort(EingangsArray, startIdx, cuttingEdge, arrayCopy, updateBars, setColor, sortSpeed);
await MergeSort(EingangsArray, cuttingEdge + 1, endIdx, arrayCopy, updateBars, setColor, sortSpeed);
// Merge halves back togeteher
await merge(EingangsArray, startIdx, cuttingEdge, endIdx, arrayCopy, updateBars, setColor, sortSpeed);
}
async function merge(EingangsArray, startIdx, middleIdx, endIdx, arrayCopy, updateBars, setColor, sortSpeed) {
let i = startIdx;
let j = middleIdx + 1;
let k = startIdx;
const bars = document.querySelectorAll('.bar'); // get all bars
const sortSpeedSwitch = Number(sortSpeed);
// index exist?
const isValidIndex = (index) => index >= 0 && index < bars.length;
// Merge halves back togeteher
while (i <= middleIdx && j <= endIdx) {
if (isValidIndex(i) && isValidIndex(j)) {
// Change color of compared bars
bars[i].style.backgroundColor = 'red';
bars[j].style.backgroundColor = 'red';
}
switch (sortSpeedSwitch) {
case 0:
break; // No delay
case 40:
await new Promise(resolve => setTimeout(resolve, 90));
break;
case 100:
await new Promise(resolve => setTimeout(resolve, 200));
break;
}
if (EingangsArray[i] <= EingangsArray[j]) {
arrayCopy[k] = EingangsArray[i];
i++;
} else {
arrayCopy[k] = EingangsArray[j];
j++;
}
// Update Array
await updateArrayState(EingangsArray, arrayCopy, startIdx, endIdx, updateBars, sortSpeed);
if (isValidIndex(i - 1)) bars[i - 1].style.backgroundColor = ''; // default colr
if (isValidIndex(j - 1)) bars[j - 1].style.backgroundColor = '';
k++;
}
// Copy from the LEFT half
while (i <= middleIdx) {
switch (sortSpeedSwitch) {
case 0:
break; // No delay
case 40:
await new Promise(resolve => setTimeout(resolve, 90));
break;
case 100:
await new Promise(resolve => setTimeout(resolve, 200));
break;
}
arrayCopy[k] = EingangsArray[i];
await updateArrayState(EingangsArray, arrayCopy, startIdx, endIdx, updateBars, sortSpeed);
if (isValidIndex(i)) bars[i].style.backgroundColor = '';
i++;
k++;
}
// Copy from the RIGHT half
while (j <= endIdx) {
switch (sortSpeedSwitch) {
case 0:
break; // No delay
case 40:
await new Promise(resolve => setTimeout(resolve, 90));
break;
case 100:
await new Promise(resolve => setTimeout(resolve, 200));
break;
}
arrayCopy[k] = EingangsArray[j];
await updateArrayState(EingangsArray, arrayCopy, startIdx, endIdx, updateBars, sortSpeed);
if (isValidIndex(j)) bars[j].style.backgroundColor = '';
j++;
k++;
}
// Copy merged values back
for (let i = startIdx; i <= endIdx; i++) {
EingangsArray[i] = arrayCopy[i];
}
// adding to class 'finished'
if (endIdx - startIdx + 1 === EingangsArray.length) {
setColor(0);
}
}
async function updateArrayState(EingangsArray, arrayCopy, startIdx, endIdx, updateBars, sortSpeed) {
updateBars([...arrayCopy]);
await new Promise(resolve => setTimeout(resolve, sortSpeed));
}
export default async function startMergeSort(EingangsArray, updateBars, setFinish, sortSpeed) {
const arrayCopy = [...EingangsArray];
await MergeSort(EingangsArray, 0, EingangsArray.length - 1, arrayCopy, updateBars, setFinish, sortSpeed);
}
...@@ -15,6 +15,9 @@ body { ...@@ -15,6 +15,9 @@ body {
height: 100px; height: 100px;
flex: 1 1 20px; flex: 1 1 20px;
min-width: 2px; min-width: 2px;
margin: 0px;
transform-origin: bottom;
} }
.sorted { .sorted {
...@@ -75,13 +78,20 @@ button:active { ...@@ -75,13 +78,20 @@ button:active {
} }
.DivArray { .DivArray {
transform: scaleY(-1);
display: flex; display: flex;
position: absolute;
position: fixed;
flex-wrap: nowrap; flex-wrap: nowrap;
justify-content: center; justify-content: center;
gap: 2px; gap: 2px;
width: 90%; width: 90%;
margin-top: 5px; margin-top: 60px;
align-items: flex-end;
overflow: hidden;
height: 400px;
/
} }
#dropdown-menu { #dropdown-menu {
...@@ -91,7 +101,6 @@ button:active { ...@@ -91,7 +101,6 @@ button:active {
margin-top: 3px; margin-top: 3px;
} }
#dropdown-item { #dropdown-item {
color: white; color: white;
font-size: 16px; font-size: 16px;
...@@ -115,7 +124,6 @@ button:active { ...@@ -115,7 +124,6 @@ button:active {
height: 100%; height: 100%;
display: flex; display: flex;
place-items: center; place-items: center;
margin-inline: 10px;
justify-content: center; justify-content: center;
width: 195px; width: 195px;
transition: none; transition: none;
...@@ -135,6 +143,17 @@ button:active { ...@@ -135,6 +143,17 @@ button:active {
color: white; color: white;
} }
.Divider {
background: gray;
height: 70%;
margin-left: 8px;
margin-right: 3px;
width: 2px;
}
#dividerLeft {
margin-right: 8px;
}
@keyframes ScaleAnimation { @keyframes ScaleAnimation {
0% { 0% {
......
import {useState, useEffect} from 'react'; import {useState, useEffect} from 'react';
import './SortingVisualizer.css' import './SortingVisualizer.css'
import BubbleSort from "./BubbleSort"; import BubbleSort from "./BubbleSort";
import startMergeSort from "./MergeSort.js";
import RangeSlider from 'react-bootstrap-range-slider'; import RangeSlider from 'react-bootstrap-range-slider';
import 'react-bootstrap-range-slider/dist/react-bootstrap-range-slider.css'; import 'react-bootstrap-range-slider/dist/react-bootstrap-range-slider.css';
import {Dropdown} from 'react-bootstrap'; import {Dropdown} from 'react-bootstrap';
...@@ -13,9 +14,10 @@ function SortingVisualizer() { ...@@ -13,9 +14,10 @@ function SortingVisualizer() {
const [BarNumber, setBarNumber] = useState(() => monitorSize > 100 ? 100 : monitorSize); // max of 100 bars const [BarNumber, setBarNumber] = useState(() => monitorSize > 100 ? 100 : monitorSize); // max of 100 bars
const [bars, setbars] = useState(() => generateArray(BarNumber)); const [bars, setbars] = useState(() => generateArray(BarNumber));
const [sorting, setSorting] = useState(false); const [sorting, setSorting] = useState(false);
const [alreadySorted, setAlreadySorted] = useState(); const [alreadySorted, setColor] = useState();
const [isSorted, setIsSorted] = useState(false); const [isSorted, setIsSorted] = useState(false);
const [sortSpeed, setSortSpeed] = useState('40'); const [sortSpeed, setSortSpeed] = useState('40');
const [Algo, setAlgo] = useState('BubbleSort');
const SliderWithInputFormControl = () => { const SliderWithInputFormControl = () => {
const [sliderValue_intern, setSliderValue_intern] = useState(BarNumber); const [sliderValue_intern, setSliderValue_intern] = useState(BarNumber);
...@@ -41,18 +43,22 @@ function SortingVisualizer() { ...@@ -41,18 +43,22 @@ function SortingVisualizer() {
} }
function generateArray(numberBars) { function generateArray(numberBars) {
return Array.from({length: numberBars}, () => getRandomArbitrary(50, 300)); return Array.from({length: numberBars}, () => getRandomArbitrary(20, 400));
} }
async function handleSorting() { async function handleSorting() {
if (sorting) return; if (sorting) return;
setSorting(true); setSorting(true);
await BubbleSort(bars, setbars, setAlreadySorted, sortSpeed); if (Algo == 'BubbleSort') {
await BubbleSort(bars, setbars, setColor, sortSpeed);
} else if (Algo == 'MergeSort') {
await startMergeSort(bars, setbars, setColor, sortSpeed);
}
setSorting(false); setSorting(false);
} }
function resetBars() { function resetBars() {
setAlreadySorted(1000); setColor(1000);
setbars(generateArray(BarNumber)); setbars(generateArray(BarNumber));
let ColoredBars = document.getElementsByClassName('sorted'); let ColoredBars = document.getElementsByClassName('sorted');
document.getElementById('startButton').innerText = 'Sort!'; document.getElementById('startButton').innerText = 'Sort!';
...@@ -73,7 +79,7 @@ function SortingVisualizer() { ...@@ -73,7 +79,7 @@ function SortingVisualizer() {
function handleButton() { function handleButton() {
if (!sorting && !isSorted) { if (!sorting && !isSorted) {
setAlreadySorted(1000); setColor(1000);
handleSorting(); handleSorting();
} else if (isSorted) { } else if (isSorted) {
resetBars(); resetBars();
...@@ -106,14 +112,15 @@ function SortingVisualizer() { ...@@ -106,14 +112,15 @@ function SortingVisualizer() {
value={BarNumber} style={{ value={BarNumber} style={{
width: '42px', width: '42px',
fontfamily: 'Arial sans-serif', fontfamily: 'Arial sans-serif',
fontSize:'16px', fontSize: '16px',
margin: '10px', marginLeft: '10px',
marginRight: '5px',
borderRadius: '5px', borderRadius: '5px',
border: 'none', border: 'none',
textAlign: 'center' textAlign: 'center'
}}/> }}/>
<div style={{background: 'gray', height: '70%', marginLeft: '10px', width: '2px'}}></div> <div id="dividerLeft" className="Divider"></div>
<Dropdown id="dropdown"> <Dropdown id="dropdown" className="dropdown-wide">
<Dropdown.Toggle <Dropdown.Toggle
id="dropdown" id="dropdown"
disabled={sorting} disabled={sorting}
...@@ -138,6 +145,26 @@ function SortingVisualizer() { ...@@ -138,6 +145,26 @@ function SortingVisualizer() {
</Dropdown.Item> </Dropdown.Item>
</Dropdown.Menu> </Dropdown.Menu>
</Dropdown> </Dropdown>
<div className="Divider"></div>
<Dropdown id="dropdown">
<Dropdown.Toggle
id="dropdown"
disabled={sorting}
>
Algorithm: {
[Algo]
}
</Dropdown.Toggle>
<Dropdown.Menu id="dropdown-menu">
<Dropdown.Item id="dropdown-item" onClick={() => setAlgo('BubbleSort')}>
BubbleSort
</Dropdown.Item>
<Dropdown.Item id="dropdown-item" onClick={() => setAlgo('MergeSort')}>
MergeSort
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
<button id='startButton' className="Button" disabled={sorting} <button id='startButton' className="Button" disabled={sorting}
style={{background: `${sorting ? 'red' : ''}`}} onClick={() => { style={{background: `${sorting ? 'red' : ''}`}} onClick={() => {
handleButton() handleButton()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment