快速排序

        快速排序是使用最多的排序方式,其复杂度为1.39NlogN,略高于归并排序,但是由于其移动次数少且不需要,所以一般情况下快速排序会更快。

        快速排序原理是将数组第一个元素作为切分元素,比其小的元素排在其左侧,比其大的元素排在其右侧,然后再分别对其两侧的子数组进行切分,最终得到排好序的数组。

        三项切分的快速排序则是在快速排序的基础上将与切分元素相等的所有元素找到并与切分元素一起排在中间,然后只对小于切分元素的左侧子数组和大于切分元素的右侧子数组进行再次切分。三项切分能将复杂度减小到N到1.39NlogN之间,从而提高快速排序方法在处理有大量重复数据的数组时的速度。

        图示和代码分别如下:



void _swap(int t[], int *lo, int *hi)              //交换两元素
{
    int temp = *lo;
    *lo = *hi;
    *hi = temp;
}

int *_partition(int t[], int *lo, int *hi)             //切分函数
{
    const int cmp = *lo;                               //记录切分元素
    int *left = lo;                                    //左半部分指针
    int *right = hi+1;                                 //右半部分指针
    while(true)
    {
        while(*(++left) < cmp) if(left >= hi) break;   //左指针右移
        while(*(--right) > cmp) if(right <= lo) break; //右指针左移
        if(left >= right) break;                       //退出循环条件
        _swap(t, left, right);                         //左指针指向大于切分元素的数,右指针指向小于切分元素的数,交换二者
    }
    _swap(t, lo, right);                               //交换切分元素与右指针指向的数(此时右指针在左指针之前)
    return right;                                      //返回右指针指向的位置(此时该位置处的值为切分元素)
}

void Quick(int t[], int *lo, int *hi)                  //标准快排
{
    if(lo >= hi) return;                               //结束递归
    int *j = _partition(t, lo, hi);
    Quick(t, lo, j-1);                                 //将切分元素前后两部分继续递归切分
    Quick(t, j+1, hi);
}

void Quick3way(int t[], int *lo, int *hi)              //三项切分的快排
{
    if(lo >= hi) return;                               //结束递归
    int cmp = *lo;
    int *left = lo;
    int *right = hi;
    int *i = lo+1;                                     
    while(i <= right)                                  //i > right表示已遍历数组
    {
        if(*i < cmp) _swap(t, left++, i++);            //i指向元素小于切分元素则交换i和left指向的元素后二者自加1
        else if(*i > cmp) _swap(t, right--, i);        //i指向元素大于切分元素则交换i和right指向元素,right自减,i不变
        else i++;                                      //i指向元素等于切分元素,则i自加
    }
    Quick3way(t, lo, left-1);                          //递归调用
    Quick3way(t, right+1, hi);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值