如何证明Hoare快速适用于任何阵列

时间:2017-12-22 13:51:43

标签: java sorting quicksort hoare-logic

试着找出为什么Hoare快速排序正常工作。基本上我无法向自己证明我们无法创建一个会导致Hoare排序算法失败的数组。证明没有必要成为100%数学。我只想相信算法有效。

在下面的代码中,我重写了算法的某些部分,以使我更清楚(基本想法保持不变)。

void quickSort(int[] arr, int start, int end) {
  int pivotIndex = partition(arr, start, end);

  if (start < pivotIndex - 1) quickSort(arr, start, pivotIndex - 1);
  if (end >= pivotIndex) quickSort(arr, pivotIndex, end);
}

int partition(int[] arr, int leftIndex, int rightIndex) {
    int pivot = arr[(leftIndex + rightIndex) / 2];

    while (true) {
        while (arr[leftIndex] < pivot) leftIndex++;
        while (arr[rightIndex] > pivot) rightIndex--;

        if (leftIndex == rightIndex) return leftIndex + 1;

        if (leftIndex < rightIndex) {
          swap(arr, leftIndex, rightIndex);
          leftIndex++;
          rightIndex--;
        }
        if (leftIndex > rightIndex) return leftIndex;
    }
}

我对这个功能100%肯定:

  1. 功能将分段数组分成两个子数组
    • - 包含小于或等于pivot的元素
    • - 包含更大或更适合转动的元素
  2. 分区完成后, leftIndex 不能大于 rightIndex 大于1.换句话说: leftIndex - rightIndex仅等于0或1
  3. 函数始终返回高子数组
  4. 中第一个元素的第一个索引

    我完全不理解:

    第一个问题:

    为什么如果代码

    if (leftIndex < rightIndex) { 
        swap(arr, leftIndex, rightIndex);
        leftIndex++;
        rightIndex--;
    }
    

    已执行,之后 leftIndex 变为等于 rightIndex ,这并不意味着数组已成功分区,我们可以返回 leftIndex + 1 ?为了澄清我的想法,请看下面的代码:

    int partition(int[] arr, int leftIndex, int rightIndex) {
        int pivot = arr[(leftIndex + rightIndex) / 2];
    
        while (true) {
            while (arr[leftIndex] < pivot) leftIndex++;
            while (arr[rightIndex] > pivot) rightIndex--;
    
            // remove line from here    
            //if (leftIndex == rightIndex) return leftIndex + 1;
    
            if (leftIndex < rightIndex) {
              swap(arr, leftIndex, rightIndex);
              leftIndex++;
              rightIndex--;
            }
            // move it here. If I do that, code stop working and sort array in a wrong way
            //sorce array: [6, 3, 12, 10, 3, 8, 5, 8, 11, 2, 9]
            //final array: [2, 3, 3, 5, 6, 8, 8, 9, 10, 12, 11] - 12 and 11 at wrong places
            if (leftIndex == rightIndex) return leftIndex + 1;
    
            if (leftIndex > rightIndex) return leftIndex;
        }
    }
    

    第二个问题:

    让我们对以下场景进行成像。假设枢轴值为10,并且下面的代码已成功执行:

        01 while (arr[leftIndex] < pivot) leftIndex++;
        02 while (arr[rightIndex] > pivot) rightIndex--;
        03 if (leftIndex == rightIndex) return leftIndex + 1;
    

    之后,假设 leftIndex rightIndex 停留在索引为 X value = 6 的元素上即 arr [X] - &gt; 6 。 第3行将使用值返回索引 X + 1 ,假设 8 。 所以基本上我们将有子数组:

    [..., ...] and [8, ..., 10, ...]
    

    如此高的子数组将包含小于pivot的元素。是否可以创建此类阵列来复制该场景?

1 个答案:

答案 0 :(得分:0)

这可能会回答您关于如何证明Hoare算法的整体问题。 This online PDF 给出了正式和非正式的证据。这是非正式的(它是一个图像因为pdf没有文字,它只是一个图像本身):

first half of informal proof second half of informal proof