快速排序

快速排序:

我们要知道,快速排序其实是冒泡排序的一种改进,冒泡排序每次对相邻的两个数进行比较,这显然是一种比较浪费时间的。

而快速排序是分别从两端开始”探测”的,先从右往左找一个小于基准点的数,再从左往右找一个大于基准点的数,然后交换它们。这里可以用两个变量i 和j ,分别指向序列最左边和最右边。我们为这两个变量起个好听的名字“哨兵i ”和“哨兵j ”。刚开始的时候让哨兵i 指向序列的最左边,指向数字。让哨兵j 指向序列的最右边。

为了方便,我们假设基准点为arr[begin]。首先哨兵j 开始出动。直到找到一个小于arr[begin]的数停下来。接下来哨兵i再一步一步向右挪动,直到找到一个数大于arr[begin]的数停下来。现在交换i和j指向的元素的值,然后重复i和j的移动和交换过程,直到第一轮探测结束。

回顾一下刚才的过程,其实哨兵j的使命就是要找小于基准数的数,而哨兵i的使命就是要找大于基准数的数,直到i和j碰头为止。(i == j)

这里值得注意的是,因为最开始是处于序列最末端的j移动的所以最后i和j碰头的时候,结果一定是arr[i] = arr[j]<arr[begin]的。到了这个时候(第一轮探测结束)我们还需要交换arr[begin]和arr[i]的值,以便使基准点arr[begin]处于分界点的位置。到此为止,第一轮探测才算真正结束,此时,比基准点小的数都排在其左边,比基准点大的数都排在其右边。

下一轮探测,无非就是以上一轮的基准点为中心分别对其左和右进行排序(分治的思想)。调用Quick_Sort(arr, begin, i-1)和Quick_Sort(arr, i+1, end)即可。

代码如下:

void Quick_Sort(int *arr, int begin, int end)//快速排序
{
    if(begin > end)
        return;
    
    int i = begin;
    int j = end;
    
    while(i != j)
    {
        while(arr[j] >= arr[begin] && j > i)
            j--;
        
        while(arr[i] <= arr[begin] && j > i)
            i++;

        if(j > i)
        {
            swap(arr[i], arr[j]);
        }
    }
    swap(arr[begin], arr[i]);
    
    Quick_Sort(arr, begin, i-1);
    Quick_Sort(arr, i+1, end);
}

那么问题来了,如果我想以arr[end]作为基准点,那么该如何实现呢?

首先需要明确的一点就是i和j的移动顺序其实是大有文章的。i先移动和j先移动得到的结果完全不一样。j (end) 先移动说明arr[i] = arr[j]<arr[begin];i (begin) 先移动说明arr[i] = arr[j]>arr[begin]。而且最后基准点是需要和arr[i]做交换的,所以我们一定需要明确,到底如何操作i和j的移动次序才能真正的达到我们的目的—比基准点小的数都排在其左边,比基准点大的数都排在其右边

arr[begin]和arr[i]交换的时候,是将arr[begin]从起点拿到中间位置,从最后的交换结果看来,是将其与比其小的数做交换。同理:arr[end]和arr[i]做交换的时候,是将其和比其大的数做交换。因此我们有结论:若以arr[begin]为基准点,则先让最右边的j移动,这样能够保证arr[i] = arr[j]<arr[begin];同理:若以arr[end]为基准点,则先让最左边的i移动,这样就能够保证arr[i] = arr[j]>arr[begin]。

代码如下:

void Quick_Sort(int *arr, int begin, int end)//快速排序
{
    if(begin > end)
        return;
    
    int i = begin;
    int j = end;
    
    while(i != j)
    {
        while(arr[i] <= arr[end] && j > i)
            i++;
        
        while(arr[j] >= arr[end] && j > i)
            j--;
    
        if(j > i)
        {
            swap(arr[i], arr[j]);
        }
    }
    swap(arr[end], arr[i]);
    
    Quick_Sort(arr, begin, i-1);
    Quick_Sort(arr, i+1, end);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值