【问题标题】:How the recursion in Quicksort algorithm works?快速排序算法中的递归如何工作?
【发布时间】:2017-01-19 08:12:19
【问题描述】:

我在 Google 中看到一些代码实现了这样的快速排序算法。

static public void QuickSort_Recursive(int [] arr, int left, int right)
{
    // For Recusrion
    if(left < right)
    {
        int pivot = Partition(arr, left, right);

        if(pivot > 1)
            QuickSort_Recursive(arr, left, pivot - 1);

        if(pivot + 1 < right)
            QuickSort_Recursive(arr, pivot + 1, right);
    }
}

我试图解决这个问题,我已经了解代码本身是如何工作的,但有一件事让我感到困惑。递归(上面的代码)如何工作。它是如何被终止的。我是递归函数的新手,我只知道它的基础。

有人可以直截了当地向我解释一下吗? :)

P.S:我知道分区部分,所以我没有包括它。

【问题讨论】:

  • 检查 (pivot > 1) (应该是 (pivot - 1 > left) 和 (pivot + 1

标签: algorithm sorting quicksort


【解决方案1】:

您可能知道,递归的工作原理是根据较小的实例定义较大的问题,并通过解决问题的较小实例并使用这些解决方案构建较大的解决方案来解决较大的问题。

在您的情况下,检查 left 子数组进行排序。

【讨论】:

  • @rcgldr 我想你误解了我所说的减小尺寸的意思。考虑到您的示例,您所描述的随着您深入递归而增加的是要解决的问题实例的数量。当然,这对于某些递归问题来说是一个问题,但这与我减少问题规模的意思无关。当我说递归通过减小大小来工作时,我的意思是问题 f(N) 是根据 f(k_i) 定义的,因此对于 i k_i 的所有值。
  • @rcgldr 我相信您提出的所有观点都是正确的,是的。但请注意,问题的重点是递归(即减少问题大小)而不是排序。我认为您的解释包含太多高效快速排序实现的理论,使事情变得复杂。 OP 清楚地询问递归如何在快速排序的特定实现上工作,而不是在快速排序的有效实现上工作。这就是为什么我的答案基于 OP 询问的特定代码,以及为什么我的答案将基本情况设为 1。
  • 看来我们对基本情况这个术语的定义有所不同。我认为,您的定义是“完成某事的问题的最小实例”。我对基本案例的想法是“通过 QuickSort_Recursive 调用的问题的最小实例”。 (即停止递归的调用)确实,对于大小
  • 看,我明白了,这就是为什么我说我们定义基本情况的方式有所不同。但是除了你之外没有人在谈论快速排序的各种实现,更不用说归并排序了! OP询问了一个特定的实现,我提供了一个具体的回应。你为什么坚持回答一个没有被问到的问题?!​​
  • OP的具体示例代码有错误。如果第二个 if 固定为 if(pivot - 1 > left),以及第三个 if(pivot + 1 = 右)。
【解决方案2】:

按顺序来说,每次递归调用都会将所有局部变量(包括函数参数)和当前代码位置压入堆栈(调用堆栈),然后跳转到函数的开头, 使用新参数。当调用完成时,它会从堆栈中弹出变量和返回地址,然后返回到调用的位置。

但理解递归的最佳方式实际上是不尝试按顺序解决它,而是将问题分解为多个部分。您通过将数组分成两部分来对数组进行排序,然后对每个部分进行排序——除非这些部分的大小为 1 或 0,以防您停止并完成该部分(这很简单,总是排序少于 2 个元素)进一步分解。

执行有点像二叉树,叶子是子数组大小为 0 或 1 的停止条件。

我建议修改如下代码:

static public void QuickSort_Recursive(int [] arr, int left, int right) {
    QuickSort_Recursive(arr, left, right, 1);
}

static public void QuickSort_Recursive(int [] arr, int left, int right, int depth)
{
    System.out.println(String.format("%"+(depth*3)+"sleft=%d, right=%d", "", left, right));
    // For Recusrion
    if(left < right)
        {
            int pivot = Partition(arr, left, right);

            if(pivot > 1)
                QuickSort_Recursive(arr, left, pivot - 1, depth+1);

            if(pivot + 1 < right)
                QuickSort_Recursive(arr, pivot + 1, right, depth+1);
        }
}

这将在每次通话时为您提供打印输出,可以帮助您了解正在发生的事情。

【讨论】:

    猜你喜欢
    • 2016-03-19
    • 2020-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    • 2020-08-14
    • 2013-10-08
    相关资源
    最近更新 更多