具有生成器函数的递归合并排序无法按预期工作

Recursive merge sort with a generator function does not work as expected

我试图观察我的递归归并排序每一步对数组进行切片。

function mergeSort(arr) {
  if(arr.length === 1) return arr;

  const mid = Math.floor(arr.length / 2);
  const leftArray = arr.slice(0, mid);
  const rightArray = arr.slice(mid, arr.length);

  console.log(leftArray, rightArray)

  return merge(mergeSort(leftArray), mergeSort(rightArray));
}

function merge(leftArray, rightArray) {
  const sortedArray = [];

  while(leftArray.length > 0 && rightArray.length > 0) {
    if(leftArray[0] < rightArray[0]) {
      sortedArray.push(leftArray[0]);
      leftArray.shift();
    } else {
      sortedArray.push(rightArray[0]);
      rightArray.shift();
    }
  }

  return sortedArray.concat(leftArray).concat(rightArray);
}

如果您看到上面的代码,我正在记录 leftArrayrightArray。但是一旦我 运行 代码,它就会立即记录每一步。为了控制代码的执行,我将我的 mergeSort 函数变成了一个生成器函数,这样每当我 运行 .next() 我就可以看到下一个切片。

function * mergeSort(arr) {
  if(arr.length === 1) return arr;

  const mid = Math.floor(arr.length / 2);
  const leftArray = arr.slice(0, mid);
  const rightArray = arr.slice(mid, arr.length);

  yield console.log(leftArray, rightArray);

  return merge(mergeSort(leftArray), mergeSort(rightArray));
}

function merge(leftArray, rightArray) {
  const sortedArray = [];

  while(leftArray.length > 0 && rightArray.length > 0) {
    if(leftArray[0] < rightArray[0]) {
      sortedArray.push(leftArray[0]);
      leftArray.shift();
    } else {
      sortedArray.push(rightArray[0]);
      rightArray.shift();
    }
  }

  return sortedArray.concat(leftArray).concat(rightArray);
}

const list = [32, 12, 23, 52, 5, 16, 74, 21, 33, 55, 85];
const sort = mergeSort(list);

sort.next(); // I expected [32, 12], [23, 52, 5]
sort.next(); // [32, 12] and so on...

原来结果不是我想的那样。如果您对生成器函数的使用提出建议,我将不胜感激!

在合并排序中,数组被分成更小的数组,直到它的大小为1。之后,它合并更小的数组,这样新创建的数组也被排序。

要了解递归,您可以使用缩进来跟踪所有递归级别。 例如:

const log = (level, data) => {
    var s = ""
    for (i = 0; i < level; i++) {
        s += "    ";
    }
    console.log(s + data);
}

const merge = (left, right) => {
  const result = [];

  while(left.length && right.length){
    if(left[0] <= right[0]){
      result.push(left.shift());
    }else{
      result.push(right.shift());
    }
  }

  while(left.length) result.push(left.shift());
  while(right.length) result.push(right.shift());
  return result;
}

const mergeSort = (array, level) => {
  log(level, "Start " + array);
  if(array.length < 2) {
    log(level, "Finish " + array);
    return array;
  }

  const middle = Math.floor(array.length / 2);
  log(level, "middle element " + array[middle])
  const leftArr = array.slice(0, middle);
  const rightArr = array.slice(middle, array.length);
  var result = merge(mergeSort(leftArr, level + 1), mergeSort(rightArr, level + 1));
  log(level, "Finish " + result);
  return result;
};

调用level值为1的函数