快速排序(C++)

快速排序是一种常见的排序方法,主要采用递归分治的思想实现

快速排序

快速排序的主要思想是分治,通过每次选取一个基准点,将比这个点数据小的元素全部放在左边,比这个点大的元素全部放在右边,此时这个基准点已经位于正确的位置上了。换句话说,经过一趟排序,将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小。然后再对被分割出来的这两部分数据进行递归处理。最终就可以得到一个排好序的数组。

递归算法的代码一般由两个函数组成,一个函数经常被称为Partition函数(C++ STL也提供了这个函数)。Partition函数所起的作用就是根据一个基准数来就地分割(就在原数组上修改而不需要引入额外的辅助数组)原数组,使得比基准元素小的数全部放在左边,大的全部放在右边(根据具体排序的需求来决定),然后返回基准元素所在的位置(这个位置也就是该元素最终在排好序的数组中的位置),并根据这个位置进行下一步的递归处理。

int Partition(vector<int> &arr, int low, int high){
    int pivot = arr[high]; //选取最后一个元素为基准元素,也可以随机选择之后跟high位置替换。
    int location = low - 1; //location代表小于pivot的数组的边界
    for (int i = low; i < high; i++){
        if (arr[i] < pivot){ //如果小于pivot
            swap(arr[i], arr[++location]); //将它放在左边数组里,边界前移一格。
        }
    }
    swap(arr[high], arr[++location]); //将Pivot元素换到正确的位置,
    return location;
}

主函数就是一个很简单的分治的过程:

void quicksort(vector<int> &arr, int low, int high)
{
    if (low < high)
    {
        int middle = Partition(arr, low, high);
        quicksort(arr, low, middle - 1);
        quicksort(arr, middle + 1, high);
    }
}

时间复杂度

递归算法的时间复杂度公式为:
T [ n ] = a T [ n b ] + f ( n ) T[n] = aT[\frac nb] + f(n)
a代表子问题的个数,f(n)代表当前这一层所花费的时间。f(n) = n,a=2。在最理想的情况下,partition中所选择的基准元素恰好把原数组平分为两部分,则此时递归的深度为logn,所以快速排序的时间复杂度为O(nlogn),这里省略了推导过程,要推的话写出公式来推几步也是比较直观的。最差的情况是每次选择的都是最大或者最小的元素作为基准元素,这样就相当于退化成了冒泡排序。时间复杂度退化为O(n^2). 总共的来说,一般认为快速排序的平均时间复杂度就是O(nlogn)。

空间复杂度

如果就算法本身来说,原地排序的空间复杂度为O(n),但实际还要考虑递归调用的函数栈也会有一定的空间消耗。

发布了76 篇原创文章 · 获赞 10 · 访问量 8266

猜你喜欢

转载自blog.csdn.net/weixin_38742280/article/details/104815824