快速排序 C++版

版权声明:本文为博主原创文章,转载请注明出处。作者:ISmileLi 博客地址:http://blog.csdn.net/toby54king。 https://blog.csdn.net/toby54king/article/details/84110147

一、实现原理看下面代码中的注释。

二、实现方法及测试代码如下:

#include <iostream>

using namespace std;

/******************************
快速排序:选一个基准数将原始数组划分成两个子数组第一个子数组是小于基准数的数
第二个子数组是大于基准数的数。然后再对两个子数组进行第归操作,直到排序完成。
基数的选择可以选择最左边、最右边、中间数或者三者中的中位数,以选中位数为最优。
优点:1、速度快 2、移动数据少
缺点:1、逻辑复杂 2、不稳定
算法时间复杂度:O(nlog(n)~n^2) 空间复杂度:O(n)+辅助空间
******************************/

// 方法一
template<typename T>
void quick_sort(T data[],int first,int last)
{
    int lower = first+1,upper = last;
    swap(data[first],data[(first+last)/2]); // 选定中间的数为基数,并把基数与第一个数交换位置
    T bound = data[first];
    while(lower<=upper)
    {
        while(data[lower] < bound) // 寻找比基数大的数
        {
            lower++;
        }
        while(bound<data[upper])// 寻找比基数小的数
        {
            upper--;
        }
        if(lower<upper)
        {
            swap(data[lower++],data[upper--]);// 把左边比基数大的和右边比基数小的数交换
        }
        else
        {
            lower++; // 跳出while
        }
    }
    swap(data[upper],data[first]);
    if(first < upper-1)
    {
        quick_sort(data,first,upper-1);
    }
    if(upper+1 < last)
    {
        quick_sort(data,upper+1,last);
    }
}

template<typename T>
void quickSort(T data[],int n)
{
    int i,max;
    if(n<2)
    {
        return;
    }

    // 预处理,把最大的数放到最右边
    for(i = 1,max = 0;i<n;i++)
    {
        if(data[max]<data[i])
        {
            max = i;
        }
    }
    swap(data[n-1],data[max]); // 把最大的数放到最右边
    quick_sort(data,0,n-2); // 快排
}

// 方法二
template<typename T>
void quickSort1(T data[],int first,int last)
{
    if(first>=last) return;

    int lower = first+1;
    int upper = last;
    T base = data[first]; // 取最左边的数为基数

    while(lower<=upper) // 必须带等号,否则有错误
    {
        while(data[lower]<base && lower<upper) // 防止基数取的是最大值,导致程序非正常中断
        {
            lower++;
        }
        while(data[upper]>base)
        {
            upper--;
        }
        if(lower<upper)
        {
            swap(data[lower++],data[upper--]);
        }
        else
        {
            lower ++;
        }
    }
    swap(data[upper],data[first]);// 把基准数放到找到的中间位置中
    if(first<upper-1)
    {
        quickSort1(data,first,upper-1);
    }
    if(upper+1<last)
    {
        quickSort1(data,upper+1,last);
    }
}

// 方法三 取最左边最右边和中间数三个数中的中位数为基准数
template<typename T>
void quickSortMid(T data[],int first,int last)
{
    if(first>=last) return;
    int lower = first,upper=last,mid=(first+last)/2;
    int min = data[first]<data[mid] ? first:mid; // 求第一个数和中间的数中的最小的数值的索引
    int midIndex = data[last]>min ? last:min; // 求最小的数和最后一个数中两者中最大的即得到三者中的中位数索引
    T base = data[midIndex];
    while(lower<=upper)
    {
        while(data[lower]<base)
        {
            lower++;
        }
        while(data[upper]>base)
        {
            upper--;
        }
        if(lower<upper)
        {
            swap(data[lower++],data[upper--]);
        }
        else
        {
            break;
        }
    }
    swap(data[upper],data[midIndex]);
    if(first<upper-1)
    {
        quickSort1(data,first,upper-1);
    }
    if(upper+1<last)
    {
        quickSort1(data,upper+1,last);
    }
}

int main(int argc, char *argv[])
{
    int tempArr[] = {0,4,3,5,6,7,9,8,2,1};
    int arrSize = sizeof(tempArr)/sizeof(tempArr[0]);
    cout << "arrSize=" << arrSize << endl;
    for(int i=0; i<arrSize; i++)
    {
        cout << tempArr[i];
    }
    cout << endl;
    //quickSort(tempArr,arrSize);
    //quickSort1(tempArr,0,arrSize);
    quickSortMid(tempArr,0,arrSize);

    for(int i=0; i<arrSize; i++)
    {
        cout << tempArr[i];
    }
    cout << endl;
    cout << "Hello World!" << endl;
    return 0;
}

三、测试结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/toby54king/article/details/84110147