Я пытался создать приложение для визуализации сортировки с помощью react. Оно генерирует случайные значения, и пользователь может выбрать метод сортировки из списка (пузырьковый, слияние и быстрое). И алгоритм отображает визуализацию сортировки по полосам. Код ниже: введите здесь описание изображения
import React,{Component} from 'react';
import getMergeSortAnimations from './Person/Person';
import bubbleSortAnimations from './Person/BubbleSort';
import './App.css';
class App extends Component{
state = {
array: [],
bar_width:2,
run:false,
colors:["#007bff","red"],
hover:[false,false,false]
};
componentDidMount() {
this.generateArray();
}
generateArray = ()=> {
const array = [];
let val = document.querySelector('#size').value;
if(val<=10)
{
this.setState({bar_width:8});
}
else if(val<=20 && val>10)
this.setState({bar_width:7});
else if(val<=50 && val>20)
this.setState({bar_width:6});
else if(val<=100 && val>50)
this.setState({bar_width:5});
else if(val<=150 && val>100)
this.setState({bar_width:3});
else if(val<=180 && val>150)
this.setState({bar_width:3});
else
this.setState({bar_width:2});
for (let i = 0; i < val; i++) {
array.push(this.randomIntFromInterval(5, 450));
}
this.setState({array});
}
changeTheme = ()=>
{
const color = document.getElementById("theme").value;
if(color==="blue")this.setState({colors:["#007bff","red"]});
else if(color==="orange")this.setState({colors:["orange","black"]});
}
randomIntFromInterval = (min, max)=> {
return Math.floor(Math.random() * (max - min + 1) + min);
}
mouseOver1 = ()=>{
this.setState({hover:[true,false,false]});
}
mouseOver2 = ()=>{
this.setState({hover:[false,true,false]});
}
mouseOver3 = ()=>{
this.setState({hover:[false,false,true]});
}
mouseOut = ()=>{
this.setState({hover:[false,false,false]});
}
mergeSort = ()=>{
let t ;
let ar = this.state.array.slice();
this.setState({run:true});
const animations = getMergeSortAnimations(ar);
for (let i = 0; i < animations.length; i++) {
const arrayBars = document.getElementsByClassName('element');
const isColorChange = i % 3 !== 2;
if (isColorChange) {
const [barOneIdx, barTwoIdx] = animations[i];
const barOneStyle = arrayBars[barOneIdx].style;
const barTwoStyle = arrayBars[barTwoIdx].style;
const color = i % 3 === 0 ? this.state.colors[1] : this.state.colors[0];
setTimeout(() => {
barOneStyle.backgroundColor = color;
barTwoStyle.backgroundColor = color;
}, i*10);
} else {
setTimeout(() => {
const [barOneIdx, newHeight] = animations[i];
const barOneStyle = arrayBars[barOneIdx].style;
barOneStyle.height = `${newHeight}px`;
}, i*10);
}
t = i+1;
}
setTimeout(()=>this.setState({run:false}),t*10);
}
bubbleSort = ()=> {
let t;
this.setState({run:true});
let ar = this.state.array.slice();
const animations = bubbleSortAnimations(ar);
for (let i = 0; i < animations.length; i++) {
const arrayBars = document.getElementsByClassName('element');
const isColorChange = i % 3 !== 2;
if (isColorChange) {
const [barOneIdx, barTwoIdx] = animations[i];
const barOneStyle = arrayBars[barOneIdx].style;
const barTwoStyle = arrayBars[barTwoIdx].style;
const color = i % 3 === 0 ? this.state.colors[1] : this.state.colors[0];
setTimeout(() => {
barOneStyle.backgroundColor = color;
barTwoStyle.backgroundColor = color;
}, i*2);
} else {
setTimeout(() => {
const [barOneIdx,barTwoIdx,firstHeight,secondHeight] = animations[i];
const barOneStyle = arrayBars[barOneIdx].style;
const barTwoStyle = arrayBars[barTwoIdx].style;
barOneStyle.height = `${firstHeight}px`;
barTwoStyle.height = `${secondHeight}px`;
}, i*2);
}
t = i+1;
}
setTimeout(()=>this.setState({run:false}),t*2);
}
render() {
return (
<div>
<header>
<label for="theme" style={{fontSize:`${20}px`}} >Theme:</label>
<select name="theme" id="theme" style={{marginBottom:`${4}px`}} onChange={this.changeTheme}>
<option value="blue">blue</option>
<option value="orange">orange</option>
<option value="green">green</option>
</select>
<div className="slidercontainer">
<input className="slider" onChange={this.generateArray} type="range" min="5" max="200" id='size'/>
</div>
<nav>
<ul>
<li><button onMouseOut={this.mouseOut} onMouseOver={this.mouseOver1} style={{color:this.state.hover[0]?"white":"black",backgroundColor:this.state.hover[0]?`${this.state.colors[0]}`:"white"}} onClick={this.generateArray} id="new">New array</button></li>
<li><button onMouseOut={this.mouseOut} onMouseOver={this.mouseOver2} style={{color:this.state.hover[1]?"white":"black",backgroundColor:this.state.hover[1]?`${this.state.colors[0]}`:"white"}} onClick={this.mergeSort} id="mergesort" disabled={this.state.run}>Merge Sort</button></li>
<li><button onMouseOut={this.mouseOut} onMouseOver={this.mouseOver3} style={{color:this.state.hover[2]?"white":"black",backgroundColor:this.state.hover[2]?`${this.state.colors[0]}`:"white"}} onClick={this.bubbleSort} id="bubbleSort" disabled={this.state.run}>Bubble sort</button></li>
</ul>
</nav>
</header>
<div className="container">
<br></br>
{this.state.array.map((value, idx) => (
<div
className="element"
key={idx}
style={{
backgroundColor:`${this.state.colors[0]}`,
width:`${this.state.bar_width}px`,
height:`${value}px`
}}></div>
))}
</div>
</div>
);
}
}
export default App;
Код для getMergeSortAnimations приведен ниже:
export default function getMergeSortAnimations(array) {
const animations = [];
mergeSort(array, 0, array.length - 1,animations);
return animations;
}
function mergeSort(array,low, high,animations) {
if(low<high)
{
const mid = Math.floor((low + high) / 2);
mergeSort(array, low, mid,animations);
mergeSort(array, mid + 1, high,animations);
merge(array, low, high,animations);
}
}
function merge(array,low,high,animations) {
let a = [];
let k = low;
let i = low;
let mid = Math.floor((low+high)/2);
let j = mid + 1;
while (i <= mid && j <= high) {
animations.push([i, j]);
animations.push([i, j]);
if (array[i] <= array[j]) {
animations.push([k, array[i]]);
a[k++] = array[i++];
} else {
animations.push([k, array[j]]);
a[k++] = array[j++];
}
}
while (i <= mid) {
animations.push([i, i]);
animations.push([i, i]);
animations.push([k, array[i]]);
a[k++] = array[i++];
}
while (j <= high) {
animations.push([j, j]);
animations.push([j, j]);
animations.push([k, array[j]]);
a[k++] = array[j++];
}
for(let o=low;o<k;o++)
{
array[o] = a[o];
}
}
Я использую массив анимаций, чтобы отслеживать изменения, внесенные в массив во время сортировки, и отражать их в DOM. Мне удалось выяснить это для пузырьков и mergeSort, но я не могу выполнить часть анимации для quicksort.
код для быстрой сортировки:
let getAnimations = (array)=>{
const animations = [];
quickSort(array,0,array.length-1,animations)
return animations;
}
let quickSort = (array,start,end,animations)=>{
if(start<end)
{
let pindex = partition(array,start,end,animations);
quickSort(array,start,pindex-1,animations);
quickSort(array,pindex+1,end,animations);}
}
let partition = (array,start,end,animations)=>{
let i=start+1;
let j=end;
let pivot = array[start];
let temp;
while( true)
{
while( i<=j && array[i]<=pivot)
{
i++;
}
while(i<=j && array[j]>=pivot )
{
j--;
}
if(i<=j)
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
else{
temp = array[start];
array[start] = array[j];
array[j] = temp;
return j;
}
}
}
Я застрял в quickSort уже несколько дней, но я не могу его взломать. Было бы очень полезно, если бы кто-нибудь мог мне помочь.
Спасибо.