小白学习快速排序~

119 阅读2分钟

快速排序可以说是面试常考题了,这里主要以“小白”的视角,用直白的“图画”来解释快速排序中“分区”的具体操作步骤。

这里的代码来自于社区整理的资料:sort.hust.cc/6.quicksort

代码:

const arr = [9, 11, 12, 13, 8, 14, 7, 6, 5, 15, 3];

function partition(arr, low, high) {
  const p = arr[low];
  while (low < high) {
    while (low < high && arr[high] > p) {
      high--;
    }
    arr[low] = arr[high];

    while (low < high && arr[low] <= p) {
      low++;
    }
    arr[high] = arr[low];
  }
  arr[low] = p;
  return low;
}

function quickSort(arr, low, high) {
  if (low < high) {
    // 1. 找到分区的基准下标
    const pivotIndex = partition(arr, low, high);
    // 2. 给分区继续分区
    quickSort(arr, low, pivotIndex - 1);
    quickSort(arr, pivotIndex + 1, high);
  }
  return arr;
}

const newArr = quickSort(arr, 0, arr.length - 1);

这里不仅解释 partition 函数具体在做什么,还要回答两个问题:

  • (1)外层 while 循环中,为什么是 low < high 而不是 low <= high?
  • (2)为什么内层循环的 while 中,需要再加 low < high 的判断?不加会怎么样?

让我们循序渐进,用图示来回答上面两个问题。先从 partition 内的第一个语句出发:

下面关键的点来了,我们试图来回答一下问题(2)为什么需要在内层 while 中增加 low < high 的问题: 如果在此时的步骤 12 中,我们去掉 low < high 判断条件,或者 low <= high,会发生什么?

image.png

image.png

image.png

image.png

好的,所以我们已经知道为什么内层 while 循环需要增加 low < high 的问题了,我们继续回到步骤12:

停!我们来看一下问题(1)为什么是外层 while 循环需要的是 low < high 而不是 low <= high?

如果 low === high,我们继续循环,只会重复 arr[low] = arr[high], 还有 arr[high] = arr[low] 语句,没有意义。所以,一旦 low === high,我们跳出循环,得到了 low ,即为 pivot 归位的下标位置。

小结:通常学习算法的时候,都知道大致的思路,但是写起来还是会“恐惧”。为什么呢,因为不知道如何进行边界判断。这就需要我们不断地去训练、扣细节,才能提升对边界判断的敏感度,有效消除这种“恐惧感”。