了解QuickSort期间的递归

时间:2016-04-25 12:29:06

标签: c++ algorithm quicksort

我是c ++的新手,并通过http://geeksquiz.com/quick-sort/

的快速排序算法

以下是代码片段,我无法理解为什么低和高的值会发生变化

int partition (int arr[], int low, int high)
{
    int pivot = arr[high];    // pivot
    int i = (low - 1);  // Index of smaller element

    for (int j = low; j <= high- 1; j++)
    {
        // If current element is smaller than or
        // equal to pivot
        if (arr[j] <= pivot)
        {
            i++;    // increment index of smaller element
            swap(&arr[i], &arr[j]);
        }
    }
    swap(&arr[i + 1], &arr[high]);
    return (i + 1);
}

/* The main function that implements QuickSort
 arr[] --> Array to be sorted,
  low  --> Starting index,
  high  --> Ending index */
void quickSort(int arr[], int low, int high)
{
    if (low < high)
    {
        /* pi is partitioning index, arr[p] is now
           at right place */
        int pi = partition(arr, low, high);

        // Separately sort elements before
        // partition and after partition
        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }
}

请帮助我理解上述逻辑。

2 个答案:

答案 0 :(得分:3)

找一个分区。 partition的后置条件是枢轴元素左侧的所有内容都小于或等于分区中的元素,并且枢轴元素右侧的所有内容都将大于或等于枢轴元素。递归左右子阵。

通过循环不变量,您将拥有一个已排序的数组。

为简单起见,我们假设您的分区始终返回中间元素。

你知道partition的帖子条件确保左边最多是枢轴元素,右边至少是枢轴元素。

现在通过递归调用low == lowhigh == pi - 1的快速排序来递归排序左侧。 pi位于正确的空间内,因此您不必担心这一点。最后,您使用low == pi+1high == high在右侧数组上调用quicksort。

重复直到所有内容都已排序(即!(low < high))。

在此图中很好地解释了递归任务(我们假设每次都是pivot的中间元素)。这也方便地显示了O(n log n)时间复杂度的平均值。

quicksort complexity explained

答案 1 :(得分:2)

您已经澄清了您的问题,即您了解partition()背后的逻辑,而不是递归。确定。

您必须从假设开始,而quickSort()将对您的数组进行排序。接受它作为给定。公理。一定是真的。您可以确信quickSort()将对您的阵列进行排序。作为一个起点,你必须接受这个陈述作为一个无可置疑的事实。

然后,您已经了解partition()将列表分为两半。基于此,您可以得出以下结论:

  1. 在pivoting元素之前的数组的一半只包含小于pivot元素的值。

  2. pivoting元素之后的数组的一半只包含大于pivot元素的值。

  3. 1&amp; 2是partition()操作的结果,您表示您完全理解。鉴于1&amp; 2,作为一个起点,你可以得出结论,如果在1和1中引用的数组的一半。 2完全自我排序,整个数组必须完全排序。

  4. 你如何制作1&amp; 2真的吗?好吧,你递归地应用quickSort()算法。您刚才同意quickSort()将对其获得的数组进行完全排序。因此,在quickSort()递归排序两半之后,最终结果必须是完全排序的列表。

  5. Q.E.D。

    P.S。上面使用的术语“阵列的一半”是一个松散使用的术语。当然,阵列的每一半的实际大小不会是原始阵列的一半。这对整体逻辑没有影响。