理解快速排序过程中的递归 我是C++的新手,从中经历一个快速排序算法
下面是我无法理解的代码片段,low和high的值是如何改变的理解快速排序过程中的递归 我是C++的新手,从中经历一个快速排序算法,c++,algorithm,quicksort,C++,Algorithm,Quicksort,下面是我无法理解的代码片段,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
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);
}
}
int分区(int-arr[],int-low,int-high)
{
int pivot=arr[high];//pivot
int i=(低-1);//较小元素的索引
对于(int j=低;j起始指数,
高-->结束索引*/
无效快速排序(整数arr[],整数低,整数高)
{
如果(低<高)
{
/*pi是分区索引,arr[p]现在是
在正确的地方*/
int pi=分区(arr、低、高);
//在之前分别对元素进行排序
//分区和分区后
快速排序(arr、低、pi-1);
快速排序(arr、pi+1、高);
}
}
请帮助我理解上述逻辑。找到一个分区。
分区的Post条件是枢轴元素左侧的所有内容都将小于或等于分区中的元素,枢轴元素右侧的所有内容都将大于或等于枢轴元素。在左、右子分区上递归雷
通过循环不变量,您将得到一个排序数组
为了简单起见,假设您的分区总是返回中间元素
通过分区的post条件
可以确保left最多是pivot元素,right至少是pivot元素
现在,通过使用low==low
和high==pi-1
递归调用quicksort对左侧进行递归排序pi
位于正确的空间中,因此不必担心这一点。最后,使用low==pi+1
和high==high
在右侧数组中调用quicksort
重复此操作,直到所有内容都已排序(即!(低<高)
)
递归任务在这个图中得到了很好的解释(我们假设每次pivot都是中间元素)。这也方便地显示了平均情况O(n logn)
的时间复杂度
查找分区。分区的Post条件是枢轴元素左侧的所有内容将小于或等于分区中的元素,枢轴元素右侧的所有内容将大于或等于枢轴元素。在左侧和右侧子数组上递归
通过循环不变量,您将得到一个排序数组
为了简单起见,假设您的分区总是返回中间元素
通过分区的post条件
可以确保left最多是pivot元素,right至少是pivot元素
现在,通过使用low==low
和high==pi-1
递归调用quicksort对左侧进行递归排序pi
位于正确的空间中,因此不必担心这一点。最后,使用low==pi+1
和high==high
在右侧数组中调用quicksort
重复此操作,直到所有内容都已排序(即!(低<高)
)
递归任务在这个图中得到了很好的解释(我们假设每次pivot都是中间元素)。这也方便地显示了平均情况O(n logn)
的时间复杂度
您已经澄清了您的问题,您理解partition()背后的逻辑,但不理解递归。好的
您必须从假设quickSort()
将对数组进行排序开始。接受它作为给定的公理。它必须是真的。您必须假设quickSort()
将对数组进行排序。您必须接受此语句作为一个毫无疑问的事实,作为一个起点
然后,您已经了解了partition()
将列表分为两部分。基于此,您可以得出以下结论:
数据透视元素之前的数组的一半只包含小于数据透视元素的值
数据透视元素后的数组的一半只包含大于数据透视元素的值
1和2是partition()
操作的结果,您表示完全理解该操作。从1和2开始,您可以得出结论,如果1和2中引用的数组的一半本身已完全排序,则整个数组将必须完全排序
那么如何使1和2为真呢?好吧,你递归地应用quickSort()
算法。你刚刚同意quickSort()
将对它得到的数组进行完全排序。因此,在quickSort()
递归地对两个半排序之后,最终结果必须是一个完全排序的列表
Q.E.D
另外,上面使用的术语“数组的一半”是一个松散使用的术语。当然,数组的每一半的实际大小不会正好是原始数组的一半。这对整体逻辑没有影响。您已经澄清了您的问题,您了解partition()背后的逻辑,但不了解递归。好的
您必须从假设quickSort()
将对数组进行排序开始。接受它作为给定的公理。它必须是真的。您必须假设quickSort()
将对数组进行排序。您必须接受此语句作为一个毫无疑问的事实,作为一个起点
然后,您已经了解了partition()
将列表分为两部分。基于此,您可以得出以下结论:
数据透视元素之前的数组的一半只包含小于数据透视元素的值
数据透视元素后的数组的一半只包含大于数据透视元素的值
1和2是partition()
操作的结果,您声明您完全理解该操作