排序算法——快速排序算法实现及改进策略

1、 时间复杂度:
最好情况:o(n);
平均情况:o(nlogn)
最坏情况:o(n^2)
2、算法步骤:
(1)从数列中选取一个元素作为基准值;
(2)小于基准值的往前面排;大于基准值的往后面排;
(3)递归对步骤二的两个子数列再次进行排序;
(4)终止条件:子数列的长度是1时结束。
3、优化策略(主要从基准值的选择、减少总的移动次数、减少比较次数角度进行)
(1)优化基准值选择:
a) 选择中间、两边位置的元素进行比较,选择中间值作为基准值;能够减少14%的比较;
b) 选择数列的中位数作为中间值;复杂度是o(n);但是缺点是进行多次比较;
(2)优化不必要的交换
将不必要的交换用赋值语句进行替换;
(3)优化小数组的排序
大数组选择快速排序比较好;但是小数组建议选择插入排序;根据数组长度为划分大小数组的依据。
(4)减少递归
改为尾递归,减少对栈的使用。
尾递归:如果一个函数中所有递归形式的调用都出现在函数的末尾,我们称这个递归函数是尾递归的。当递归调用是整个函数体中最后执行的语句且它的返回值不属于表达式的一部分时,这个递归调用就是尾递归。尾递归函数的特点是在回归过程中不用做任何操作,
当编译器检测到一个函数调用是尾递归的时候,它就覆盖当前的活动记录而不是在栈中去创建一个新的。编译器可以做到这点,因为递归调用是当前活跃期内最后一条待执行的语句,于是当这个调用返回时栈帧中并没有其他事情可做,因此也就没有保存栈帧的必要了。通过覆盖当前的栈帧而不是在其之上重新添加一个,这样所使用的栈空间就大大缩减了,这使得实际的运行效率会变得更高。
4、随机化快速排序算法实现代码

/***************************************************************************
*  @file       main.cpp
*  @author     HAOJIEFENGLANG
*  @date       5  August 2018
*  @remark     5  August 2017
*  @theme      Quick Sort
***************************************************************************/
#include <iostream>
#include <vector>

using namespace std;
//函数声明
void Fast_sort(int a[], int left, int right);
int partion(int a[], int left, int right);
void Swap(int &a, int &b);
int Rand(int low, int high);

int main()
{
    int a[] = { 1,4,74,2,6,3,9,4,8,21};
    int length = 0; 
    length = sizeof(a) / sizeof(int);
    Fast_sort(a, 0, length-1);
    for (size_t i = 0; i != length; ++i)
        cout << a[i] << " ";
    cin.get();
    return 0;
}

//标准递归版本的快速排序
void Fast_sort(int a[], int left, int right)
{
    if (left < right)
    {
        int index = partion(a, left, right);//partion也可以
        Fast_sort(a, left, index - 1);
        Fast_sort(a, index + 1, right);
        //Fast_sort(a, left, index - 1);尾递归形式
        //left=index + 1;
    }
}

int partion(int a[], int left, int right)//首先进行分区操作
{
    Swap(a[Rand(left, right)], a[left]);//随机选择区间的一个数,将其与首元素进行交换
    int flag = a[left];//将首元素当作标杆
    int j = left;
    for (int i = left + 1; i <= right; ++i)//首先忽略首元素
    {
        if (a[i] < flag)
        {
            j++;
            if (j != i)
            {
                //Swap(a[i], a[j]);//将标杆数一直往右移动,遇到比标杆数小的就交换到从头开始的位置上
                Swap(a[j], a[i]);
            }
        }
    }

    //Swap(a[j], a[left]);//j位置的元素和首元素互换,即可保证标杆元素左边为小于等于,右边为大于等于
    Swap(a[left], a[j]);
    return j;
}

void Swap(int &a, int &b)
{
    int temp = a;
    a = b;
    b = temp;
}


//取区间内随机数的函数  
int Rand(int low, int high)
{
    int size = high - low + 1;
    return  low + rand() % size;
}

猜你喜欢

转载自blog.csdn.net/haojiefenglang/article/details/81430312