代码之家  ›  专栏  ›  技术社区  ›  No Name QA

快速排序霍尔阵列分区

  •  0
  • No Name QA  · 技术社区  · 8 年前

    试图弄明白为什么霍尔分区算法总是将数组分成两个正确的部分。在下面的代码中,我扩展了 Hoare algorithm 让我更清楚(详情见评论)

    int partition(int[] arr, int leftIndex, int rightIndex) {
      int pivot = arr[(leftIndex + rightIndex) / 2];
    
      while (leftIndex <= rightIndex) {
        while (arr[leftIndex] < pivot) leftIndex++;
        while (arr[rightIndex] > pivot) rightIndex--;
    
        // If all numbers at right places, than leftIndex and rightIndex 
        // could point at same array element index
        // So it's means partion done. 
        // We should return leftIndex + 1 cause 
        // rightIndex points at the last element of the left sub array
    
        if (leftIndex == rightIndex) return leftIndex + 1; 
    
        if (leftIndex < rightIndex) {
          swap(arr, leftIndex, rightIndex);
          leftIndex++;
          rightIndex--;
        }
      }
    
      //But here the tricky thing: Why does this "if case" never execute?
      if (leftIndex - 1 > rightIndex) 
        System.out.println("leftIndex - 1 > rightIndex");
    
      return leftIndex;
    }
    

    所以问题是:是否有可能将数组传递给分区函数,从而执行下面的行?

    if (leftIndex - 1 > rightIndex) 
      System.out.println("leftIndex - 1 > rightIndex");?
    
    1 回复  |  直到 8 年前
        1
  •  2
  •   xs0    8 年前

    要执行该函数,leftIndex必须至少为rightIndex+2,如果我们用leftIndex启动函数,那么这是不可能的<=rightIndex(右索引):

    使用这两个循环:

    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--;
    }
    

    即使他们尽可能接近( leftIndex == rightIndex - 1 ),执行后,他们将在 leftIndex == rightIndex + 1 . 我们仍然没有得到2的差值。