基础算法改进——快速排序的改进

基础算法改进——快速排序的改进

简介:
快排三种实现方式:

  1. 挖坑法
  2. 左右指针法
  3. 前后指针法
    在这里插入图片描述
    在这里插入图片描述

改进方法:

  1. 随机化: 数组打乱random_shuffle(a+1,a+n+1); //打乱它
  2. 小区间插入排序:减少对栈的访问
  3. 基准选择:
    - 随机:但是随机数的生成本身是一种代价,根本减少不了算法其余部分的平均运行时间。
    - 三值取中数:经验得知,选取左端,右端,中心元素的中值会减少快排大约 14%的比较。
    - 中位数:选取中位数的可以在 O(n)时间内完成。(在平均情况下,任何顺序统计量(特别是中位数)都可以在线性时间内得到)
  4. 三路快速排序算法:划分成三部分:小于、等于、大于
  5. 消除递归:利用栈

挖坑法实现快排,代码如下:

template<class T>//插入排序
void CC_InsertSort(T* begin, int Len)
{
    T t, * A = begin;
    int i, j;
    for (i = 1; i <= Len; i++)
        if (A[i] < A[i - 1]) {
            t = A[i];
            for (j = i - 1; j >= 0 && A[j] > t; j--)
                A[j + 1] = A[j];
            A[j + 1] = t;

        }
}

template<class T>//挖坑快速排序
int partition(T* begin, int Len) {
   
    T* A = begin;
    int Tem = A[0];//选取比较的基准,其位置也就是初始的坑位

    int i = 0, j = Len - 1;
    while(i < j) {
        while (A[j] >= Tem && i < j)
            j--;
        if(i < j)
            A[i++] = A[j];
        while (A[i] <= Tem && i < j)
            i++;
        if (i < j)
            A[j--] = A[i];
    }
    A[j] = Tem;
    return j;
}

template<class T>
void CC_QuickSort(T* A,int Len)
{
    if (Len <= 1) return;
    int k = partition(A, Len);
    CC_QuickSort<int>(A, k);
    CC_QuickSort<int>(&A[k+1], Len - k-1);
}

改进算法:

选取(a,b,c)(左端,右端,中心元素)三个数的中位数的方法:

  • m = max(a,b); n = max(b,c);
  • 如果m==n ,说明b是三者最大的,那么(a,c)中的最大值就是三者的中值
  • 否则:如果m和n都不等于b,说明b是三者最小的那个,那么(a,c)中的较小者就是三者的中值
  • 否则,(a,c)一个大于b一个小于b,说明b为中值。

template<class T>//插入排序
void CC_InsertSort(T* begin, int Len)
{
    T t, * A = begin;
    int i, j;
    for (i = 1; i <= Len; i++)
        if (A[i] < A[i - 1]) {
            t = A[i];
            for (j = i - 1; j >= 0 && A[j] > t; j--)
                A[j + 1] = A[j];
            A[j + 1] = t;

        }
}


template<class T>//返回左端,右端,中心元素的中值的位置
int GetMid(T* begin, int Len) {
    if (Len <= 1)
        return 0;
    int a = begin[0], b = begin[Len / 2], c = begin[Len-1];
    int m = std::max(a, b), n = std::max(b, c);
    if (m == n)
        if (a > c)
            return 0;
        else
            return Len-1;
    else if (m != b && n!= b)
        if (a > c)
            return Len-1;
        else
            return 0;
    else
        return Len / 2;
    
}


template<class T>//挖坑快速排序
int partition(T* begin, int Len) {

    T* A = begin;
    int mid = GetMid<int>(begin, Len);//中位
    std::swap(A[mid], A[0]);//把中位数换到第一位
    int Tem = A[0];//选取比较的基准,其位置也就是初始的坑位
 
    int i = 0, j = Len - 1;
    while(i < j) {
        while (A[j] >= Tem && i < j)
            j--;
        if(i < j)
            A[i++] = A[j];
        while (A[i] <= Tem && i < j)
            i++;
        if (i < j)
            A[j--] = A[i];
    }
    A[j] = Tem;
    return j;
}



template<class T>
void CC_QuickSort(T* A,int Len)
{
    if (Len <= 1) return;
    if (Len < 15) { //小区间采用插入排序
        CC_InsertSort(A, Len-1);
        return;
    }
    int k = partition(A, Len);
    CC_QuickSort<int>(A, k);
    CC_QuickSort<int>(&A[k+1], Len - k-1);
}


posted @ 2022-03-05 16:00  Cheney822  阅读(171)  评论(0编辑  收藏  举报