在介绍一般化的选择问题之前,需要用到一些前置知识,是快速排序中的数组划分。在一般化的选择问题中,正确的划分数组可以很大程度上降低时间复杂度极大地提高效率。这个划分过程的数学证明比较复杂,我们主要学习其中的思路与方法。
下面是快速排序中数组划分并在原址重新排列的代码。
int psort(A[],l,r)
{
int x=A[r];
int i=l-1;
for(int j=l;j<=r-1;j++)
{
if(A[j]<=x)
{
i+=1;
swap(A[i],A[j]);
}
}
swap(A[i+1],A[r]);
return i+1;
}
从代码中我们可以看到,我们划分数组时,首先需要选择一个元素作为主元,并围绕主元来划分子数组。在执行过程中,我们实际上将数组划分为了四个部分。对于数组中某一元素下标而言,当时,这里的元素都小于等于主元;当时,这里的元素都大于主元;当时,这里的元素还没有进入循环还没有进行大小的比较和分组,随着循环的执行这一部分的元素会越来越少直到空集;当时,这个元素是主元。
在循环结束后,我们会发现主元仍然位于数组最末端,而如果则意味着主元前面存在比主元大的元素,我们需要把主元与最左端的大于主元的元素交换,这样就能保证主元左边全部是小于等于主元的元素,右边全部是大于主元的元素,并返回主元的新下标,这样就完成了一次迭代。我们可以保证主元是处在最终排序好的位置,而左右两边的数组则不能保证组内是有序的,这也就是需要我们进行下一步的迭代,分别处理左右两边的数组。
以上是快速选择排序中数组划分的算法思想,在一般化的选择问题中对这种思想进行了进一步的改进,使得我们能更好地解决选择问题。