二分思想下的快速排序

快速排序作为最常见的排序方法,本身是对冒泡排序的改良。其拥有较高的兼容性和在理想情况下O(nlogn)的时间复杂度,是基本的排序算法之一。

快速排序所运用的基本思想是分治思想下的二分思想,故快速排序也被称为二分排序。其排序方式分为两步:

(1)二分查找:将序列对半折成两部分,如果序列单调则有左半部分的任意数都大于/小于右半部分。对于一段序列我们可以取中间值mid,将左右两部分分开查找是否存在逆序对。若不存在逆序对则说明序列单调。二分查找由于每次都将序列对半分,故其理想时间复杂度是O(logn)。

(2)交换排序:如果我们找到了一组逆序对,则说明序列暂时不单调,我们需要对逆序对进行交换处理使得序列趋于单调。

快速排序的递归方式就是通过不断的二分进行左右部分逆序对的交换,最终实现将非单调序列变为单调序列。

应用场景:给定一个长度为n的序列,将其变为升序的单调序列并一一输出。

代码实现:

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn = 100100;
int n , f[maxn];
void qsort(int l , int r) {
    int i=l , j=r , mid=f[(l+r)/2]; //左端值,右端值,中心值
    while(i <= j) {
        while(f[i] < mid) i++;//二分找到大于中值的左边数
        while(f[j] > mid) j--;//二分找到小于中值的右边数
        if(i <=j) {//找到一对逆序对
            swap(f[i] , f[j]);//对逆序对进行交换处理
            i++ , j--;
        }
    }
    if(l <j) qsort(l , j);//l<j则说明在l与j间仍存在逆序对,递归
    if(i <r) qsort(i , r);//i<r则说明在i与r间仍存在逆序对,递归
}
int main() {
    cin >> n;
    for(int i=1 ; i<=n ; i++)
        cin >> f[i]; 
    qsort(1 , n); //二分排序
    for(int i=1 ; i<=n ; i++)
        cout << f[i] << " "; 
    return 0;
}

算法时间复杂度分析:快速排序的每次划分都需要从两端点向中心进行搜索,故基本复杂度是O(n),而整个算法的时间复杂度与所划分的次数有关,理想情况下每次的划分都能分为几乎相等的两部分,所以理想复杂度是O(nlogn),在最坏情况下,即所给序列几乎为单调的情况时,需要对长度为n的序列进行n次划分,最终复杂度是O(n^2)。

所以为了避免最坏情况,有时可先将所给序列进行随机化处理再进行排序,这样几乎可以保证理想情况下的时间复杂度。

整体来说,快速排序的时间复杂度较为优秀,因此,该排序方法也被认为是目前最好的一种内部排序方法。

当然,快速排序在c++有内部的函数,被包含在头文件#include<algorithm>中,其默认为升序排序。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值