排序算法之快速排序

来源:互联网 发布:决战武进宠物进阶数据 编辑:程序博客网 时间:2024/05/19 03:17

快速排序是典型的采用分治法进行排序的算法,即将一个长序列分割成短序列进行排序。快排的平均时间复杂度是O(n*log(n))。
快排的核心思想就是每次递归将一个基数放在它在整个序列排列的正确位置,即比它小的值都在他的左边,比它大的值都在他的右边。为了实现这一点,我们需要两个指针spoint和epoint,分别指向序列的起点和终点。spoint从起点向中间遍历,找到比基数大的数(升序排列如此),epoint从终点向中间遍历,找到比基数小的数(升序排列如此),找到之后将两个数交换,从而使较小的数在左边,较大的数在右边,直到spoint和epoint指向同一个数。之后以基数所在位置为基准,将整个序列分割成两个序列,递归执行两个序列。递归终止的条件是当序列长度为1。
每次递归都要进行循环,那么在循环的开始我们便遇到一个问题,spoint所指向的第一个值即基准值究竟是否参与循环内的交换,还是在循环结束时与epoint指向的值进行交换。两种思路均能实现,下面是代码。
第一种:忽略相同的值

template<typename T>void swap(T &x, T &y){    T temp = y;    y = x;    x = temp;    count ++;}template <typename T>void quickSort(T arr[], int start, int end){    if(start>=end)        return;    T base = arr[start];    int spoint = start, epoint = end;    while(spoint != epoint){        while(spoint < epoint && arr[spoint] <= base)            spoint ++;        while(spoint < epoint && arr[epoint] >base)            epoint --;        ::swap(arr[spoint], arr[epoint]);    }    //最后要将epoint指针指向正确的位置    while(epoint > start && arr[epoint] > base)        epoint --;    ::swap(arr[start], arr[epoint]);    quickSort(arr, start, epoint-1);    quickSort(arr, epoint+1, end);}

第二种:不忽略相同值

template<typename T>void swap(T &x, T &y){    T temp = y;    y = x;    x = temp;    count++;}template <typename T>void quickSort(T arr[], int start, int end){    if(start>=end)        return;    T base = arr[start];    int spoint = start, epoint = end;    while(spoint != epoint){        while(spoint < epoint && arr[spoint] < base)            spoint ++;        while(spoint < epoint && arr[epoint] >base)            epoint --;        //如果值相同的话要将spoint向前前进一位,否则会陷入死循环。        if(spoint < epoint && arr[spoint] == arr[epoint])            spoint ++;        else            ::swap(arr[spoint], arr[epoint]);    }    quickSort(arr, start, spoint-1);    quickSort(arr, spoint+1, end);}

两种方法都能实现排序,但是第二种方法的效率较低一种要低一些,因为交换的次数要多一些,但是大致是相等的。

0 0
原创粉丝点击