【排序算法-5】快速排序法

一.基本思想

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列,其实快速排序是基于一种叫做“分治”的思想,快速排序法是目前公认的最佳排序法。

具体来说就是在data[]中任选一个记录作为基准(Pivot),以此基准将当前无序区划分为左、右两个较小的子区间,并使左边子区间中所有记录的关键字均小于等于基准记录的关键字,右边的子区间中所有记录的关键字均大于等于基准记录的关键字, 并且接下来递归的再以同样的方式排序两个子序列,但之前的基准记录关键字将不再参与之后的排序;

分治法的基本思想

将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地解这些子问题,然后将这些子问题的解组合为原问题的解。

二. 例子

用实际的数据来说明原理,这样最有说服力

data[] = 3,9,2,7,5,0,8,10做升序排序

首先任意选取data[0] = 3作为基准数,以这个数划分数据,使3左边的数据全部小于3, 3右边的数据全部大于3;
在初始状态下,数字3在序列的第1位。我们的目标是将3挪到序列的某个合适的位置位置,假设这个位置是k。现在就需要寻找这个k,并且以第k位为分界点,左边的数都小于等于3,右边的数都大于等于3.

可以通过以下方式做到:
设置两个变量 m = 0, n = data[].lenght - 1分别表示data数据的最左边和最右边;

  1. 先从n开始从右向左找比3小的数,n=5 代表的数据为0 时, 0 < 3, 此时从右向左寻找完毕, 此时 m = 0, n = 5;

  2. 再从m开始从左往右找比3大的数,m=1, 代表的数据为9时,9 > 3,
    此时从左往右寻找完毕, 此时m = 1, n = 5;

  3. 交换数据下标m = 1, n = 5代表的数据, 即交换数据data[1] = 0data[5] = 9,此时数组变成
    data[] = 3,0,2,7,5,9,8,10
    m = 1, n = 5

  4. 再从n开始从右往左找比3小的数, 当n = 2 代表的数据data[2] = 2 < 3, 此时从右往左寻找完毕, 此时m = 1, n = 2;

  5. 再从m开始从左往右找比3大的数, 如果m = n时还没找到 此时m = 2, n = 2; 则说明一轮排序结束, 此时需要交换m = 2时的数据data[2] = 2 和 基准数3, 最终一轮结束后的排序呢结果是:
    data[] = 2,0,3,7,5,9,8,10
    这样最终通过基准数3将data数据分为了两份, 分别是小于3data1[] = 2, 0, 和大于3的部分data2[] = 7, 5, 9, 8, 10

  6. 接着使用同样的方式分别对data1[] = 2, 0data2[] = 7, 5, 9, 8, 10 进行排序操作.

三. 分析:

名称 时间复杂度/最好情况 时间复杂度/最坏情况 时间复杂度/平均情况 空间复杂度/最好情况 空间复杂度/最坏情况 稳定性
直接插入排序 O(nlog2n) O(n^2) O(nlog2n) O(nlog2n) O(n) 不稳定

在最快及平均情况下,时间复杂度为O(nlog2n)。
最坏情况是每次挑中的 支点值不是最大就是最小,其时间复杂度为O(n2)。
在最差的情况下,空间复杂度为O(n),而最佳情况为O(log2n)

四. 代码

#include <iostream>
#include<iomanip>
using namespace std;
#define N 8//待排序元素个数

void display(int *data, int length);
void quickSort(int *data, int left, int right);

//输出函数
void display(int *data, int length)
{
    for(int i = 0; i < length; i++)
    {
        cout<< data[i] <<" ";
    }
    cout<< endl;
}

//快速排序
void quickSort(int *data, int left, int right)
{
    if(left > right)
    {
        return;
    }
    int m = left;
    int n = right;
    int pivot = data[left];//选取最左边的数据为基准数
    int temp;

    while(m != n)
    {
        //从右往左查找小于基准数的位置
        while(data[n] >= pivot && m < n)
        {
            n--;
        }
        //从左往右查找大于基准数的位置
        while(data[m] <= pivot && m < n)
        {
            m++;
        }
        //交换左右两边找的数据
        if(m < n)
        {
            temp = data[m];
            data[m] = data[n];
            data[n] = temp;
        }
    }
    //将基准书归位
    data[left] = data[m];
    data[m] = pivot;

    cout<< "快速排序中: ";
    display(data, N);

    quickSort(data, left, m - 1); //同样的排序方式处理左边的
    quickSort(data, m + 1, right); //同样的排序方式处理右边的

}

int main()
{
    int data[N] = {3, 9, 2, 7, 5, 0, 8, 10};
    cout<< "原始数据为:" <<endl;
    display(data, N);

    cout<<endl<< "快速排序:" <<endl;
    //快速排序调用
    quickSort(data, 0, N-1);

    cout<<endl<<"快速排序后的数据:" <<endl;
    display(data, N);
    return 0;
}

data[] = 3,9,2,7,5,0,8,10做升序排序,
结果及其排序过程如图:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/u010784887/article/details/79512037