为什么当我改变状态时排序不能正常工作?

Why doesn't sorting work correctly when I change state?

我有 BubbleSort 组件,但是当我开始排序过程时出现问题,我的排序不正确。我敢肯定,算法本身是正确编写的。我想设置状态过程有问题,但无法弄清楚它可能是什么。

import React, {Component} from "react";
import ArrayView from "../ArrayView/ArrayView";

export default class BubbleSort extends Component{
  state = {
    elements: this.props.elements
  }

    sort = () => {
    const length = this.state.elements.length;
    for (let i = 0; i < length; i++) {
      for (let j = i + 1; j < length; j++) {
        if (this.state.elements[i].value > this.state.elements[j].value) {
          this.swap(i, j);
        }
      }
    }
  }

  swap = (first, second) => {
    this.setState((state) => {
      const newElements = [...state.elements];

      const temp = newElements[first];
      newElements[first] = newElements[second];
      newElements[second] = temp;

      return {
        elements: newElements
      }
    })
  }

  render() {
    const { elements } = this.state;

    return (
      <ArrayView elements={elements} onSort={this.sort} />
    )
  }
}

问题是您每次都在交换状态中的元素,而不是在您实际排序的数组中交换它们 sort(本地 elements数组)。所以后续对 sort 中的局部 elements 数组的操作继续使用旧值,这意味着冒泡排序将无法正常工作。

除非您希望您的组件在每次交换时更新 DOM(这意味着对其进行重大更改),否则只需更改状态一次,在完成排序后设置新数组。

您不需要在交换功能中设置新状态。

交换元素并在排序函数中设置新状态,如下所示:

sort = () => {
    const elements = [...this.state.elements];

    const length = elements.length;
    for (let i = 0; i < length; i++) {
      for (let j = i + 1; j < length; j++) {
        if (elements[i].value > elements[j].value) {
          const temp = elements[i];
          elements[i] = elements[j];
          elements[j] = temp;
        }
      }
    }
    this.setState({ elements });
  }

由于您想逐步显示排序过程,您可以在交换后的每个状态更新之间添加延迟,使用 Promiseasync-await 语法。

BubbleSort组件中,添加如下两个函数:

  1. 在交换操作后的每个状态更新之间添加延迟

    sleep(seconds) {
       return new Promise((resolve, reject) => {
           setTimeout(resolve, seconds * 1000);
       });
    };
    
  2. 在嵌套循环内的每个交换操作后将调用 sleep() 函数的排序函数

    async sort() {
      const elements = [...this.state.elements];
      const length = elements.length;
    
       for (let i = 0; i < length; i++) {
         for (let j = i + 1; j < length; j++) {
           if (this.state.elements[i].value > this.state.elements[j].value) {
              const temp = elements[i];
              elements[i] = elements[j];
              elements[j] = temp;
    
             this.setState({ elements });
    
             await this.sleep(1.5);
           }
         }
       }
    };
    

演示: