代码之家  ›  专栏  ›  技术社区  ›  Chris Leung

将此快速排序实现的比较器从<=更改为<会导致无限递归。为什么?

  •  0
  • Chris Leung  · 技术社区  · 8 年前

    在分区方法中,有两个“left<=right”谓词(在其第一个while语句和最后一个if语句中)。当left==right时,在这些索引处交换元素与不交换相同,因此我认为删除比较的“==”部分不会有任何影响。然而,当我这样做并使用“left<right”运行代码时,程序无限递归(在某些输入上),并导致堆栈溢出。为什么?

    澄清:在(1)first while语句和(2)final if语句中,我正在将分区方法中的“left<=right”谓词更新为“left<right”。

    P、 由于“left”在最后一个if语句中递增,我也尝试返回left+1,但这仍然会导致无限递归。

    public static void quickSort(int[] arr, int left, int right) {
        int index = partition(arr, left, right);
        if (left < index - 1) { // Sort left half
            quickSort(arr, left, index - 1);
        }
        if (index < right) { // Sort right half
            quickSort(arr, index, right);
        }
    }
    
    public static int partition(int[] arr, int left, int right) {
        int pivot = arr[(left + right) / 2]; // Pick a pivot point. Can be an element        
        while (left <= right) {
            // Find element on left that should be on right
            while (arr[left] < pivot) { 
                left++;
            }
    
            // Find element on right that should be on left
            while (arr[right] > pivot) {
                right--;
            }
    
            // Swap elements, and move left and right indices
            if (left <= right) {
                swap(arr, left, right);
                left++;
                right--;
            }
        }
        return left; 
    }
    
    public static void swap(int[] array, int i, int j) {
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }
    
    1 回复  |  直到 8 年前
        1
  •  2
  •   niemmi    8 年前

    让我们举一个简单的例子,其中要排序的数组是 {1, 2} . 什么时候 quicksort 第一次调用 left 0 , right 1 partition 哪里 pivot 1. arr[right] > pivot 正当 将递减,但 左边 保持不变。

    因为在年底 while 分区中的循环 left < right 将返回 它是0并且被分配给 index

    下一个 left < index - 1 是假的。第二个分支将自 index < right 就在那里 快速排序 指数 其值为 1. 分别地现在如果我们从一开始就看出来 快速排序 最初使用完全相同的值调用,这解释了无限递归。

    如果你回来 left + 1 取而代之的是 指数 {1, 1} 你会对第一个分支产生完全相同的问题 快速排序