了解快速排序期间的递归
Posted
技术标签:
【中文标题】了解快速排序期间的递归【英文标题】:Understanding recursion during QuickSort 【发布时间】:2016-04-25 12:29:06 【问题描述】:我是 C++ 新手,正在经历来自 http://geeksquiz.com/quick-sort/ 的一种快速排序算法
这里是sn-p的代码,我无法理解low和high的值怎么变了
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);
请帮我理解上面的逻辑。
【问题讨论】:
理解这个逻辑的最好方法是拿出一张纸和一支铅笔,写下一个小数组,比如五个元素。然后,一次一行地浏览partition()
中的代码,跟踪每个变量和数组的内容。
low
和 high
只是递归排序的边界
@SamVarshavchik 我可以理解 partition() 背后的逻辑。我无法理解的一件事是递归逻辑和低值更新。由于函数中没有我们正在更新低/高的值。
【参考方案1】:
找到一个分区。 partition
的后置条件是枢轴元素左侧的所有内容都小于或等于分区元素,枢轴元素右侧的所有内容都大于或等于枢轴元素。递归左右子数组。
通过循环不变量,您将拥有一个排序数组。
为简单起见,假设您的分区始终返回中间元素。
您知道partition
的后置条件确保left 最多是pivot 元素,right 至少是pivot 元素。
您现在通过使用low == low
和high == pi - 1
递归调用快速排序来递归左排序。 pi
位于正确的空间中,因此您无需担心。最后,您使用low == pi+1
和high == high
在正确的数组上调用快速排序。
重复直到所有内容都排序完毕(即!(low < high)
)。
递归任务在这张图中得到了很好的解释(我们假设枢轴每次都是中间元素)。这也方便地显示了平均情况 O(n log n)
时间复杂度。
【讨论】:
谢谢埃里普...但我想了解低/高值在逻辑的哪一步得到更新。 @vivek 您在每个递归级别上分别用pi-1
和pi+1
更新high
和low
。这对应于左右子数组的递归。【参考方案2】:
您已澄清您的问题,即您了解 partition() 背后的逻辑,但不了解递归。好的。
您必须先假设quickSort()
将对您的数组进行排序。接受它作为一个给定的。一个公理。一定是真的。您确信quickSort()
将对您的数组进行排序。你必须接受这句话作为一个不容置疑的真理,作为一个起点。
那么,您已经了解partition()
将列表分为两半。基于此,您可以得出以下结论:
在枢轴元素之前的一半数组只包含小于枢轴元素的值。
在枢轴元素之后的数组的一半只包含大于枢轴元素的值。
1 和 2 是 partition()
操作的结果,您说您完全理解。以 1 和 2 为起点,您可以得出结论,如果 1 和 2 中引用的数组的一半本身是完全排序的,那么整个数组就必须是完全排序的。
你如何使 1 和 2 为真?好吧,你递归地应用quickSort()
算法。您刚刚同意quickSort()
将对它获得的数组进行完全排序。所以,quickSort()
对两半递归排序后,最终的结果一定是一个完全排序的列表。
Q.E.D.
附:上面使用的术语“阵列的一半”是一个松散使用的术语。当然,每一半数组的实际大小不会正好是原始数组的一半。这对整体逻辑没有影响。
【讨论】:
以上是关于了解快速排序期间的递归的主要内容,如果未能解决你的问题,请参考以下文章