归并排序

归并算法: 将数据先拆分为两部分,被两部分里面再拆分为两部分,然后再合并

其思想是将原始数组切分成较小的数组,直到每个小数组只有一个位置,接着将小数组归并成较大的数组,直到最后只有一个排序完毕的大数组。

 

归并排序是一种分而治之算法。其思想是将原始数组切分成较小的数组,直到每个小数组只有一个位置,接着将小数组归并成较大的数组,直到最后只有一个排序完毕的大数组。

由于是分治法,归并排序也是递归的。我们要将算法分为两个函数:第一个负责将一个大数组分为多个小数组并调用用来排序的辅助函数。我们来看看在这里声明的主要函数。

function mergeSort(array, compareFn = defaultCompare) {
  if (array.length > 1) { // {1}
    const { length } = array;
    const middle = Math.floor(length / 2); // {2}
    const left = mergeSort(array.slice(0, middle), compareFn); // {3}
    const right = mergeSort(array.slice(middle, length), compareFn); // {4}
    array = merge(left, right, compareFn); // {5}
  }
  return array;
}

归并排序将一个大数组转化为多个小数组直到其中只有一个项。由于算法是递归的,我们需要一个停止条件,在这里此条件是判断数组的长度是否为1(行{1})。如果是,则直接返回这个长度为1的数组,因为它已排序了。

如果数组长度比1大,那么得将其分成小数组。为此,首先得找到数组的中间位(行{2}),找到后我们将数组分成两个小数组,分别叫作left(行{3})和right(行{4})。left数组由索引0至中间索引的元素组成,而right数组由中间索引至原始数组最后一个位置的元素组成。行{3}和行{4}将会对自身调用mainSort函数直到left数组和right数组的大小小于等于1。

下面的步骤是调用merge函数(行{6}),它负责合并和排序小数组来产生大数组,直到回到原始数组并已排序完成。merge函数如下所示。

function merge(left, right, compareFn) {
  let i = 0; // {6}
  let j = 0;
  const result = [];
  while (i < left.length && j < right.length) { // {7}
    result.push(
      compareFn(left[i], right[j]) === Compare.LESS_THAN ? left[i++] : right[j++]
    ); // {8}
  }
  return result.concat(i < left.length ? left.slice(i) : right.slice(j)); // {9}
}

merge函数接收两个数组作为参数,并将它们归并至一个大数组。排序发生在归并过程中。首先,需要声明归并过程要创建的新数组以及用来迭代两个数组(leftright数组)所需的两个变量(行{6})。迭代两个数组的过程中(行{7}),我们比较来自left数组的项是否比来自right数组的项小。如果是,将该项从left数组添加至归并结果数组,并递增用于迭代数组的控制变量(行{8});否则,从right数组添加项并递增用于迭代数组的控制变量。

接下来,将left数组所有剩余的项添加到归并数组中,right数组也是一样(行{9})。最后,将归并数组作为结果返回。

如果执行mergeSort函数,下图是具体的执行过程。

可以看到,算法首先将原始数组分割直至只有一个元素的子数组,然后开始归并。归并过程也会完成排序,直至原始数组完全合并并完成排序。

 

posted @ 2019-10-20 11:23  1点  阅读(265)  评论(0编辑  收藏  举报