You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何以最左元素为基准时,快速排序不能从左侧开始分区?

Hoare分区法选最左元素为基准时,为何不能从左侧开始分区?

我正在使用Hoare分区法实现快速排序,代码如下:

private static int partition(int[] arr, int startIndex, int endIndex) {
    int pivot = arr[startIndex];
    int i = startIndex;
    int j = endIndex;
    while (i != j) {
        while (i < j && arr[i] <= pivot) {
            i++;
        }
        while (i < j && arr[j] > pivot) {
            j--;
        }
        if (i < j) {
            swap(arr, i, j);
        }
    }
    swap(arr, startIndex, i);
    return i;
}

我选择最左侧元素作为基准,从左索引开始分区时发现该实现无法正常工作,但从右侧开始分区则可正常运行。我想了解为何以最左元素为基准时,不能从左侧索引开始分区?


核心原因:相遇点元素的性质不符合分区要求

当基准选在数组最左侧时,必须先从右侧(j)开始遍历,否则会导致最后i、j相遇的位置元素大于基准,交换后破坏分区逻辑,具体拆解如下:

  • 先左后右的遍历逻辑缺陷
    你的代码中先移动i:只要arr[i] <= pivot就i++,直到找到第一个大于pivot的元素或i=j。
    举个反例:数组[3,4,2],基准是最左的3。

    • 初始i=0,j=2。i先移动:arr[0]<=3→i=1;arr[1]=4>3,停止左遍历。
    • 再移动j:arr[2]=2>3不成立,j保持2。此时i=1<j=2,交换arr[1]和arr[2],数组变为[3,2,4]。
    • 继续循环:i=1,j=2。i再次移动:arr[1]=2<=3→i=2,此时i=j,退出循环。
    • 交换基准位置(0)和相遇点(2),数组变为[4,2,3]。此时基准3的左侧出现了大于它的4,分区完全失效。
  • 先右后左的合理性
    如果先从j开始遍历:只要arr[j]>pivot就j--,直到找到第一个<=pivot的元素或i=j。
    最后i、j相遇的位置,元素一定是<=pivot的——因为要么是j停在这个位置,要么是i移动到j的位置(此时j已经找到符合条件的元素)。
    把基准和这个位置交换后,基准左侧的元素都会<=它,右侧都会>它,符合Hoare分区的规则。

  • 本质逻辑
    Hoare分区的核心是让基准最终处于正确位置:左边元素<=基准,右边元素>基准。当基准在最左时,我们需要保证最后交换到基准位置的元素是<=它的,而先从右侧遍历才能确保这一点。

内容的提问来源于stack exchange,提问作者hawarden_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 17:27:24