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

时间:2017-09-09 21:15:24

标签: java algorithm sorting recursion quicksort

我正在研究下面的Quicksort实施(来自Cracking the Coding Interview)。

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

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

否则,使用“left< = right”时解决方案正常。

P.S。由于“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 个答案:

答案 0 :(得分:2)

让我们举一个简单的例子,其中要排序的数组是{1, 2}。首次quicksort left0调用right时,1partition。这些值将转发到pivot,其中1将为arr[right] > pivot。由于right left会递减,但while仍然相同。

因为在分区left < right中的partition循环结束时,所以没有交换任何东西,并且循环将退出,因为它具有相同的条件。 left将返回index,该值为0并分配给quicksort

下一个left < index - 1将跳过第一个分支,因为index < right为false。第二个分支将从quicksort开始执行,index被称为right0,其值分别为1quicksort。现在,如果我们在开始时看到left + 1最初被调用时具有完全相同的值,这解释了无限递归。

如果您返回index而不是{1, 1}在第一次分区后输入quicksort将为2,那么{{1}}中的第一个分支将出现完全相同的问题。