[C语言实现]快速排序O(n²)——处理有序及相同序列优化

本文讨论了在快速排序中,针对有序序列选择中间值作为key以避免时间复杂度降为O(n²),以及在相同序列时采用三路划分的方法。通过优化取key策略,实现更高效的排序算法。
摘要由CSDN通过智能技术生成


🥰作者: FlashRider

🌏专栏: 初阶数据结构

🍖知识概要:快速排序在某些特定情况下时间复杂度会降为O(n²),我们就来探讨一下在这些情况下如何优化快速排序的时间复杂度。

目录

有序序列——取中为key

相同序列——三路划分

综合优化——最优美的快排


有序序列——取中为key

 对于有序的序列,快速排序每一趟如果选最左端点为key,那么排完一趟后比key小的数为0个,所以会浪费很多性能,而且这样选n次key,那么时间复杂度就会降低为n²。

对于有序序列的优化就是,我们可以将mid取为key,不要每次选最大或最小的为key即可。

//取key方式1 直取mid
int key = left + right >> 1;//等价于(left + right)/2
//取key方式2 三数取中
int get_key(int a[], int left, int right)
{
    int mid = (left + right) / 2;
	if (a[left] < a[mid])
	{
		if (a[mid] < a[right])
		{
			return mid;
		}
		else if (a[left] < a[right])
		{
			return right;
		}
		else
		{
			return left;
		}
	}
	else // a[left] > a[mid]
	{
		if (a[mid] > a[right])
		{
			return mid;
		}
		else if (a[left] > a[right])
		{
			return right;
		}
		else
		{
			return left;
		}
	}
}
int key = get_key(a, left, right);

相同序列——三路划分

Left Right Current 三个指针。

取left为key 则cur == key cur++。

cur < key 与left交换且cur++ left++ cur>key 与right交换且right-- cur不++ (因为要使得left永远指向与key相等的值)

cur 与 right 过之交臂(cur > right)时结束,此时left和right在等于key区间的左右端点处。

最终呈现 小于key 等于key 大于key 的三个区间。

left左边为左区间 right右边为右区间

void QuickSort(int* a, int begin, int end)
{
    if(begin >= end) return;    
	int left = begin, right = end;
    int cur = begin + 1;
    int key = get_key();//详见三数取中
    while(cur < right)
    {
        if(a[cur] == key) cur++;
        else if(a[cur] < key) swap(a[cur++], a[left++]);
        else swap(a[cur], a[right--]);
    }
    QuickSort(a, begin, left);
    QuickSort(a, right, end);
}

综合优化——最优美的快排

void sort(int q[], int l, int r)//需要考虑边界问题 
//(没有用key作下标, 递归用的i和j,需要考虑key本身位置)
{
	if(l >= r) return;
	int x = q[l];
	int i = l - 1, j = r + 1;
	while(i < j)
	{
		do i++; while(q[i] < x);
		do j--; while(q[j] > x);
		if(i < j)
			swap(q[i], q[j]);
	}
	sort(q, l, j), sort(q, j + 1, r);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值