quick_sort的递归部分如何工作?

时间:2011-10-18 20:28:43

标签: c++

以下是在许多地方找到的quick_sort的实现,包括wikipedia

这是我的简单概要。

  • 选择一个枢轴元素 - 左右½。
  • 在右侧开始索引并向左迭代。
  • 如果元素[右]< P选择翻转。
  • 在左侧开始索引并向右迭代。
  • 如果元素[左]> P选择翻转。
  • 翻转这两个元素。
  • 重复支点
  • 每半年递归重复

有人可以解释两个递归线背后的原因:

if (left < j)quick_sort(arr, left, j);
if (i < right)quick_sort(arr, i, right);

段:

  void quick_sort(int arr[], int left, int right) 
    {  
    int i = left, j = right;
    int tmp;
    int pivot = arr[(left + right) / 2];
    while (i <= j)
      {
      while (arr[i] < pivot)i++;
      while (arr[j] > pivot)j--;
      if (i <= j) 
        {
        tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
        i++;
        j--;
        }
      }
    if (left < j)quick_sort(arr, left, j);
    if (i < right)quick_sort(arr, i, right);
  }

4 个答案:

答案 0 :(得分:1)

快速排序背后的想法是围绕枢轴点交换值。但问题是,只是因为你交换了一个恰好位于数组中间的枢轴点并不意味着你已经交换了数组中值的最佳中值。因此,一旦ij的索引到达枢轴点,并且所有值都相对于该轴心点进行排序,您现在必须从数据集的左侧和右侧进行递归。枢轴,并确保阵列的每个“分支”也围绕每个相应的枢轴点进行最佳排序。最终,您将达到数组只有一个值的点,并且不会再进行交换,因为这些奇异值最佳地“交换”(即,它们 枢轴)。

你在评论中提到你被所有“跳跃”所困扰,但实际上发生的事情是快速排序反映了填写二叉搜索树时发生的过程。二叉搜索树的根类似于第一个枢轴。然后,插入树中的每个值都将根据该透视值进行排序。然后,每个递归调用的pivot值变为二叉搜索树的子树根。例如,从根开始,您有两个子树。数组中的每个值都将根据根的“数值”进行排序,但只有落在左侧的值(即,小于根值)将与左子树根进行比较“枢”。所有大于root pivot-value的值都是如此...它们将与右子树根值进行比较。然后,此过程将继续,直到所有值都插入到二叉搜索树中。最后,快速排序和插入二叉搜索树的平均复杂度为O(N log N),最坏情况复杂度为O(N)。

答案 1 :(得分:1)

如果您从数组开始:

  

[74,32,39,15,25,82,23,2,97,62,95,34,92,84,28]

它选择中间的元素(23),并分区:

  

[15 2] 23 [32 74 32 39 25 82 97 62 95 34 92 84 28]

请注意,列表未排序。由于左侧有多个,因此它会调用自己对左侧分区进行排序。

  

[15 2] ...

它选择中间(15)和分区:

  

[2] 15 ...

然后由于左(1个元素)和右(0个元素)都少于两个元素,它返回。

  

2 15 23 [74 32 39 25 82 97 62 95 34 92 84 28]

现在右边仍然有多个元素,因此它调用自己对正确的分区进行排序。

  

... [74 32 39 25 82 97 62 95 34 92 84 28]

它选择中间(97)和分区:

  

... [74 32 39 25 82 62 95 34 92 84 28] 97

现在左边有多个元素,所以它调用自己对左边的分区进行排序......

...等

最终它到达了所有子集都被排序的点,并返回到第一个:

  

2 15 23 25 28 32 34 39 62 74 82 84 92 95 97

已经完成了!

(我并没有故意选择不好的枢轴,excel为我选择了数字。很好的例子,有时枢轴不是很棒的。)

答案 2 :(得分:0)

每次在此示例中使用递归时,您使用较小部分的数据,在其上执行quick_sort:枢轴元素数据的左右两个用于一次又一次地排序,直到每个&# 39;半&#39;排序。

答案 3 :(得分:0)

在递归调用之前,算法将元素分成两个分区:所有元素都小于左边的数据透视图,所有元素都大于右边的数据透视图。枢轴位于这两个分区的中间。现在这告诉了我们关于事物状况的信息?

要对数组进行排序,小于数据透视的元素不能移动到它的右边:它们在那里是不合适的。所以这些元素永远不会从“较小”​​的分区中换出。这同样适用于“更大”分区上的元素。由此我们还可以得出结论,枢轴已经处于最终的休息位置:左侧没有任何元素会与它交换,右侧没有元素会与它交换。

因此,对枢轴进行排序后,剩下的就是对剩下的两个分区进行排序。由于我们知道我们不需要将任何元素交换出其分区,因此我们可以单独对每个分区进行排序。我们该怎么做?我们使用手头的排序算法:quicksort!

但是如果我们还没有完成算法呢,它将如何运作呢?

我们在每个分区上调用quicksort。这会将每一个分成两个分区,并再将一个枢轴放入其最后的休息处。然后在每个新分区上启动另一级快速排序。并且每次都使用相继较小的分区,直到最终分区足够小以至于不需要排序:单个元素的分区已经被排序。这是if测试的用武之地:他们测试分区是否足够大,需要排序。如果是,请对其进行快速排序;如果不是,那就完成了工作。