一.快排的思想

学习快排的时候遇到了两个板子,搞得我十分困惑,实际上是两种理解,现记录下来。
快排的思想主要是分治。
第一种做法:

  1. 确定一个枢轴元素
  2. 以枢轴为界将数组划分为两半,左边小于等于枢轴,右边大于等于枢轴
  3. 对枢轴的两半分别快排
    第一种做法是比较常见的,也是教材中经常出现的。这种思想每次划分时都会确定枢轴元素的位置,partition之后的分界点就是枢轴元素在最后结果中的位置。也就是每次partition之后返回的位置实际上就是选取的枢轴的元素的最终位置。

第二种做法:

  1. 确定一个枢轴元素
  2. 将数组划分为两半,左边小于等于枢轴,右遍大于等于枢轴。
  3. 对左右两半分别快排
    这种划分方法也是正确的,但是最后partition之后返回的分界点是两半数组的分界点,左边数组元素小于等于枢轴,右边数组有元素大于等于枢轴,但并不是枢轴元素的最终位置,枢轴元素不一定会在分界点上。

二.快排的模板

对应第一种做法:

int partition(int low,int high)
{
    swap(a[low],a[(low + high) / 2]);
    int pivot = a[low];
    while(low < high)
    {
        while(low < high && a[high] >= pivot) high--;
        a[low] = a[high];
        while(low < high && a[low] <= pivot) low++;
        a[high] = a[low];
    }
    a[low] = pivot;
    return low;
}

void quick_sort(int low,int high)
{
    if(low < high)
    {
        int pivotloc = partition(low,high);
        quick_sort(low,pivotloc-1);
        quick_sort(pivotloc+1,high);
    }
}

对应第二种做法:

void quick_sort(int a[],int low,int high)
{
    if(low >= high) return;
    //int a[low];
    int pivot = a[(low + high)/2],i = low - 1,j = high + 1;
    
    while(i < j)
    {
        while(a[++i] < pivot);
        while(a[--j] > pivot);
        
        if(i < j) swap(a[i],a[j]);
    }
    
    quick_sort(low,j);
    quick_sort(j + 1,high);
}

第二种做法必须注意边界问题,但是用左端点作为枢轴时,quick_sort内不能使用i作为分界点,因为会导致死循环。比如1,2.只需要记住一个正确的板子就可避开所有的边界条件。第一次见到这个代码的时候发现每次partition后枢轴不是在分界点的位置,但是我以往的知识告诉我每次partition之后枢轴都会在正确的位置上,搞得我十分疑惑。后来想了想,才发现每次partition之后的分界点将数组分为小于等于和大于等于的两半,但是枢轴元素不一定在分界点上。

posted on 2022-01-10 13:44  huangxk23  阅读(62)  评论(0)    收藏  举报