快速排序

来源:互联网 发布:淘宝手机端店招素材 编辑:程序博客网 时间:2024/06/03 16:57

快速排序是冒泡排序的升级版,都是通过不断交换数据来进行排序。快速排序的基本思想是:选出一个关键字,通过一次遍历,把比关键字小的数据都放到关键字左边,把比关键字大的数据都放到关键字的右边。然后在对左右两边依次进行快速排序。

由此可以看出,第一步关键字的选择很大程度上决定了快速排序的性能,如果关键字刚好选到了在中间左右的数据,那么经过一次排序后会把整段数据分成两段基本相等的数据,在进行下去效率就比较高;若果一不小心选择了最大或者最小的数据,那么一次排序下来相当于只排好了一个数据,相当不划算。为了提高性能,通常使用三数取中的方法来选取关键字,由于数据是随机排列的,可以分别在数组的左端、右端、和中间各取一个数,然后把最大的和最小的去掉,留下中间的值作为关键字,三个数同时都取得较大或者较小的概率比较小,因此可以接受。在部分情况下,还会用到九数取中的方法,就是分别取三组三个数,把三组的中数再作比较留下中间的值。

快速排序是一种不稳定的排序,其时间复杂度为O(nlogn)空间复杂度为O(logn)~O(n)

//快速排序函数//L[]为待排序序列,low为最低位的下标,high为最高位的下标void QuickSort(int L[], int low, int high){    int middle = 0;                   //middle为关键字返回的下标    while (low < high) {        middle = Partition(L,low,high);  //把关键字排好位置返回其下标        QuickSort(L, low, middle - 1);       //对关键字左边的部分进行递归快速排序        low = middle + 1;              //对关键字右边的部分进行递归快速排序            }}

//将关键字排好顺序,这是快速排序中最重要的步骤//L[]为待排序序列,low为最低位的下标,high为最高位的下标int Partition(int L[],int low, int high){    int middlekey = 0;        //首先通过三数取中算法得到比较中值得关键字    int m = low + (high - low) / 2;      //计算数组中间元素下标    if(L[low] > L[high])    {        swap(L, low, high);       //保证高位得数比低位的大    }        if(L[m] > L[high])    {        swap(L, m, high);         //保证高位得数比中间的的大    }        if (L[low] < L[m])    {        swap(L, low, m);          //把三个数的中间值放在L[low]的位置上    }        middlekey = L[low];    L[0] = middlekey;             //把选出来的中值备份到L[0]的位置上    while (low < high && L[high] >= middlekey)    //当后面的值一直比中值打,则不用交换,high向前移动    {        high--;    }        //如果跳出while循环则代表高位的值比中值小,把高位的值覆盖到低位    L[low] = L[high];             //此函数返回的是中值的下标,因此数据替换掉没有关系           //对低位的处理和高位一样    while (low < high && L[low] <= middlekey)    {        low++;    }    L[high] = L[low];    L[low] = L[0];    return low;    }

快速排序的时间复杂度:

最坏的情况:所选的关键字每次都是最大值或者最小值,这样的话快速排序就成了冒泡排序,时间复杂度为O(n^2)

最优/平均情况:第一次调用partition将整个数组扫描一遍,做n次比较。递归logn次,所以时间复杂度为O(nlogn)


空间复杂度:

最坏情况:进行n - 1次递归调用,其空间复杂度为O(n)

平均情况:O(logn)


0 0
原创粉丝点击