算法_交换排序之快速排序

思路

在表中随机选一个元素作为基准,将表划分成两个子表,其中左子表元素小于等于基准,右子表大于等于基准,基准归位。然后对子表再进行划分,直到某个子表的元素小于2。此时表中元素已有序。

实现

void quick_sort(RceType R[], int s, int t)
{
    int i, pivot;
    pivot = (s + t) / 2;
    if (s < t)
    {
        if (pivot != s)
            swpa(R, s, pivot);
        i = partition(R, s, t);
        quick_sort(R, s, i-1);
        quick_sort(R, i+1, t);
    }
}

int partition(RecType R[], int low, int high)
{
    int i = low, j = high;
    RecType tmp;
    while (i < j)
    {
        while (j > i && R[j].key >= tmp.key)
            j--;
        R[i] = R[j];
        while (i < j && R[i].key <= tmp.key)
            i++;
        R[j] = R[i];
    }
    R[i] = tmp;
    return i;
}

算法分析

时间复杂度

快速排序的算法执行过程可用对应的递归树进行描述

  • 最好:元素序列尽可能的无序,此时每趟划分的左右子表的长度都尽可能的相近,此时排序过程的递归树的高度最小,可以近似看成一棵完全2叉树,所以算法划分时间复杂度为
    O ( l o g 2 n ) O(log_2{n}) O(log2n)
    而每趟划分的时间复杂度为
    O ( n ) O(n) O(n)
    所以算法的最好时间复杂度为
    O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)
    因此最好时间复杂度达到基于比较的排序算法的最好时间复杂度

  • 最坏:与插入类排序或冒泡排序相反,当元素序列呈正序或反序时,算法执行过程近似的描述成一棵单支数,此时树的高度最大,所以算法划分时间复杂度为
    O ( n ) O(n) O(n)
    每趟划分的时间复杂度不变,所以算法的最坏时间复杂度为
    O ( n 2 ) O(n^2) O(n2)

  • 平均:接近最好时间复杂度
    O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)

空间复杂度

每次划分的临时变量与问题规模无关,但划分次数与问题规模有关——快速排序的过程可以描述成一棵递归树,而树高与问题规n模相关,所以空间复杂度为
O ( l o g 2 n ) O(log_2{n}) O(log2n)

稳定性

不稳定,举一反例即可证明

应用场景

因为快速排序是根据基准元素进行子表的划分,并且一趟划分以后基准元素归位,所以基准元素与左、右子表的大小关系就确定了。因此快速排序可以应用于求序列中的前k个最大或最小的数。

思路
  1. 直接插入排序 --> 使元素有序 --> 输出前k个元素

    时间复杂度为
    O ( n 2 ) O(n^2) O(n2)

  2. 冒泡排序 --> 冒出前k个最小元素 --> 结束算法

    时间复杂度为
    O ( k n ) O(kn) O(kn)

  3. 快速排序 --> 划分 --> 如果基准为第k个元素 --> 输出

    时间复杂度为
    O ( n ) O ( n ) O(n)O(n) O(n)O(n)
    对应实现算法

    void solution(int R[], int s, int t, int k)
    {
    	if ((k-1 > t) || (k-1 < 0))
    		return ;
    	else if (s < t)
    	{
    		int i, pivot;
    		pivot = (s + t) / 2;
    		if (s != pivot)
    			swap(R, s, pivot);
    		i = partition(R, s, t);
    		if (i == k-1)
    		{
    			print_num(R, i);
    			return ;
    		}
    		else if (k-1 < i)
    			solution(R, s, i-1, k);
    		else
    			solution(R, i+1, t, k);
    	}
    	else if (s == t)
    		print_num(R, s);
    }
    
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值