八种排序算法(一)------快速排序

算法思想

找一个基准值,本题中基准值为数组中最右的元素,再定义两个指针begin(指向首元素)、end(指向尾元素);

begin从前往后走找比基准值大的元素,找到后停下;end从后往前走找比基准值小的元素,找到后也停下;然后,交换arry[begin]和arry[end],依次循环操作;

当begin与end相遇,将arry[begin]或arry[end]与基准值交换

八种排序算法(一)------快速排序_第1张图片

代码实现(递归):

#include 

int PartSort(int* a,int right,int left)
{
    int key = a[right];
    int keyid = key;
    while(right > left)
    {
        while(right > left || a[left] <= key)
            ++left;
        while(left < right || a[right] >= key)
            --right;
        if(a[left] != a[right])
            Qswap(&a[left],&a[right]);
    }
    Qswap(&a[left],&a[keyid]);
    return left;
}

//递归实现
void QuickSort(int *a,int left,int right)
{
    if(a == NULL || right < 0 || left < 0)
        return 0;
    if(left < right)
    {
        int div = PartSort(a,left,right);

        QuickSort(a,left,div-1);
        QuickSort(a,div+1,right);
    }

}

算法优化

三数取中法

选择这组数据的第一个元素、中间元素、最后一个元素,这三个元素里面值居中的元素作为基准数;

代码实现:

#include
int Max(int a,int b)
{
    return a>b?a:b;
}
int Min(int a,int b)
{
    return a>b?b:a;
}

int GetMidIndex(int* a,int left,int right)
{
    if(a == NULL || left<0 || right < 0)
        return 0;
    int mid = left + (right - left)>>1;
    int max1 = Max(a[left],a[right]);
    int max2 = Max(a[mid],Min(a[left],a[right]));
    int MidIndex = Min(max1,max2);

    return MidIndex;

    
}

非递归实现:

#include
#include
using namespace std;

class Sort
{
    public:
    void Quick_sort(int *arr,int len)
    {
        std::stack Stack;
        if(arr == NULL || len < 0)
            return ;
        int left = 0;
        int right = len - 1;
        int pivot = 0;
    
        Stack.push(left);
        Stack.push(right);
        
        while(!Stack.empty())
        {
            int begin = Stack.top();
            Stack.pop();
            int end = Stack.top();
            Stack.pop();
            
            pivot = PartSort(arr,begin,end);
            if(begin

复杂度分析

八种排序算法(一)------快速排序_第2张图片

快速排序的时间代价很大程度上取决于枢轴的选择,最简单的办法就是选择第一个记录或者最后一个记录作为枢轴值,但这样做的弊端在于当原始的输入序列已经有序,每次分割会将剩余的记录全部分到一个序列当中,而另外一个序列为空。这种情况也是最差的情况(eg:第一趟经过n-1次比较,第一个记录定在原始位置,左半子序列为空,右半子序列为n-1个记录;第二趟n-1个经过n-2次比较,第2个记录定在原始位置,左半子序列仍为空,右半子序列为n-2个记录,以此类推,共需进行n-1趟排序,其比较次数为[(n-1)+(n-2)+......+(n-(n-1))]=n(n-1)/2=O(n^2)【时间复杂度取最高项,然后忽略掉其系数】;

最好的情况就是,每次分割都恰好将记录序列分为两个长度相等的子1序列。初始的n个记录序列,第一次分割为两个长度为n/2的子序列,第2次分割为4个长度为n/4的子序列,以此类推,总共需要分割logn次,所有分割步数之和为n,因此最终的时间复杂度为O(nlogn).

稳定性

因为快速排序每次移动记录的跨度比较大,因此快排是不稳定的。

你可能感兴趣的:(数据结构,排序算法--快排)