计算机考研补充知识数据结构相关(三) | 青训营笔记

93 阅读2分钟

在介绍一般化的选择问题之前,需要用到一些前置知识,是快速排序中的数组划分。在一般化的选择问题中,正确的划分数组可以很大程度上降低时间复杂度极大地提高效率。这个划分过程的数学证明比较复杂,我们主要学习其中的思路与方法。

下面是快速排序中数组划分并在原址重新排列的代码。

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;
}

从代码中我们可以看到,我们划分数组时,首先需要选择一个元素x=A[r]x=A[r]作为主元,并围绕主元来划分子数组。在执行过程中,我们实际上将数组划分为了四个部分。对于数组中某一元素下标kk而言,当l<=k<=il<=k<=i时,这里的元素都小于等于主元;当i+1<=k<=j1i+1<=k<=j-1时,这里的元素都大于主元;当j<=k<=r1j<=k<=r-1时,这里的元素还没有进入循环还没有进行大小的比较和分组,随着循环的执行这一部分的元素会越来越少直到空集;当k==rk==r时,这个元素是主元。

在循环结束后,我们会发现主元仍然位于数组最末端,而如果i+1!=ri+1!=r则意味着主元前面存在比主元大的元素,我们需要把主元与最左端的大于主元的元素交换,这样就能保证主元左边全部是小于等于主元的元素,右边全部是大于主元的元素,并返回主元的新下标,这样就完成了一次迭代。我们可以保证主元是处在最终排序好的位置,而左右两边的数组则不能保证组内是有序的,这也就是需要我们进行下一步的迭代,分别处理左右两边的数组。

以上是快速选择排序中数组划分的算法思想,在一般化的选择问题中对这种思想进行了进一步的改进,使得我们能更好地解决选择问题。