快速排序(Quick Sort)

正如名字一样,快速排序是实践中最快的排序算法,平均运行时间为O(N log N)。最坏情形为O(N^2),但最坏情况很容易规避。
排序步骤如下:
1. 如果集合S中只有0个或1个元素,则返回。
2. 取S中任一元素p,称为轴(pivot)。
3. 将S - {p} 这个集合分成两个子集合,集合S1中的元素小于v,集合S2中的元素大于v。
4. 继续对子集合S1和S2进行如上3个步骤。

由以上步骤可知,快速排序的效率取决于轴元素的选取,如果每次都选到最大或者最小的元素作为轴,则效率低下。最理想的情况是每次都选到中位数作为轴,使得每次的子集合S1和S2中的元素数目都相等。

但是取到一组元素的中值会耗费很多时间,因此折中后最常使用的方法是三数中值分割法(Median-of-Three Partitioning)。即分别取第一个元素,最后一个元素,以及第N/2个元素,然后取这三个数的中间值作为轴。

排序的第一步是交换轴元素与最后一个元素的位置
输入数据:
8 1 4 9 6 3 5 2 7 0 S[i]=8,S[p]=6,S[j]=0
8 1 4 9 0 3 5 2 7 6 交换S[p]和S[j],然后令j指向S[p-1],因此S[i]=8,S[j]=7,此时S[p]为最后一个元素
然后将i右移,直到遇到不小于S[p]=6的元素
将j左移,直到遇到不大于S[p]的元素
此时如果i在j的左边,则交换i和j指向的元素值,然后继续上面移动
如果i在j的右边,则不再交换了,此时交换i和p指向的元素值,然后对i左边以及i右边的序列再分别做快速排序。
代码实现如下(以下实现并未使用median-of-three):

#include<iostream>

using namespace std;

void QuickSort(int input[], int begin, int end);

int main()
{       
        int list[] = {8, 7, 6, 5, 0, 3, 2, 1, 1};
        QuickSort(list, 0, 8);
        return 0;
}

void QuickSort(int list[], int begin, int end)
{
        if (begin >= end)//由于未使用三数中值法,因此会存在begin<end的异常情况
                ;
        else if (end - begin == 1) //如果只有2个元素,则直接比较,不做快排
        {
                if (list[begin] > list[end])
                {
                        int tmp = list[end];
                        list[end] = list[begin];
                        list[begin] = tmp;
                }
        }
        else
        {
                int pivot = (begin + end) / 2;//简单起见这里以序列中间的值代替三数中值法
                int i, j;
                i = list[pivot];//交换pivot和最后一个元素,三数中值此处应是和倒数第二个元素交换,因为最后一个元素肯定比pivot大
                list[pivot] = list[end];
                list[end] = i;
                i = begin - 1;
                j = end;//由于移位时用的是++i,因此这里i做了-1,j做了+1,不然会漏掉第一个和倒数第二个元素,用三数中值时则不存在这个问题,其i = begin,j = end - 1
                while (true)
                {
                        while (list[++i] < list[end]){}
                        while (list[--j] > list[end] && j >= begin){}
                //这里j >= begin是考虑pivot取到最小值时的情况,三数中值法不存在这个问题
                        if (i < j) //如果i在j左边,则做交换
                        {
                             int tmp = list[i];
                             list[i] = list[j];
                             list[j] = tmp;
                        }
                        else //i在j右边,则排序结束
                             break;
                }
                int tmp = list[i];
                list[i] = list[end];
                list[end] = tmp;
//排序结束后需交换i和pivot的元素值

                QuickSort(list, begin, i - 1);
                QuickSort(list, i + 1, end);
        }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值