logi c создание для проекта - PullRequest
0 голосов
/ 29 мая 2020

Я пытался создать приложение для визуализации сортировки с помощью 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 уже несколько дней, но я не могу его взломать. Было бы очень полезно, если бы кто-нибудь мог мне помочь.

Спасибо.

...