快速排序(C语言)

文章详细介绍了快速排序的基本思想,通过分治策略,以基准值将序列分为两部分,并递归地对子序列进行排序。文中提到了三种不同的划分方法:Hoare版本、挖坑法和前后指针法,并提供了相应的代码实现。此外,还讨论了快速排序的时间复杂度为O(N*logN),空间复杂度为O(logN),但其稳定性较差。
摘要由CSDN通过智能技术生成

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法。
基本思想:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

void QuickSort(int* a,int left,int right)
{
    if(right-left <= 1)
    {
        return;
    }
    //[left,keyi-1] keyi [keyi+1,right]
    // 左边比keyi小        右边比keyi大
    //从中间划分
    int keyi = partsort(a,left,right);
    QuickSort(a,left,keyi-1);
    QuickSort(a,keyi+1,right);
}

可以发现,快排跟二叉树的前序遍历非常相似,只需分析如何按照基准值来对区间中数据进行划分的方式。

将区间按照基准值划分为左右两半部分的常见方式有:

  1. hoare版本
    keyi在左边,右边先走。
    keyi在右边,左边先走。
    右边找比keyi小的,左边找比keyi大的;
int PartSort1(int* a, int begin, int end)
{
	int key = a[begin];
	while (begin < end)
	{
		// end 找小
		while (begin < end && a[end] >= key)
			--end;
 
		// begin找大
		while (begin < end && a[begin] <= key)
			++begin;
 
		Swap(&a[begin], &a[end]);
	}
  //最后的交换一定要保证a[begin] < a[start], 所以要从右边走
	Swap(&a[begin], key);
	return begin;
}
 
void QuickSort(int* a, int left, int right)
{
	if (left >= right)
	{
		return;
	}
	int keyi = PartSort1(a, left, right);
	QuickSort(a, left, keyi - 1);
	QuickSort(a, keyi + 1, right);
}

2.挖坑法

// 快速排序挖坑法
int PartSort2(int* a, int left, int right)
{
	int key = a[left];
	int hole = left;
	while (left < right)
	{
		while (left < right && a[right] >= key)
		{
			right--;
		}
		a[hole] = a[right];
		hole = right;
		while (left < right && a[left] <= key)
		{
			left++;
		}
		a[hole] = a[left];
		hole = left;
	}
	a[hole] = key;
	return hole;
}

void QuickSort(int* a, int left, int right)
{
	if (left >= right)
	{
		return;
	}
	int keyi = PartSort2(a, left, right);
	QuickSort(a, left, keyi - 1);
	QuickSort(a, keyi + 1, right);
}

3.前后指针



// 快速排序前后指针法
int PartSort3(int* a, int left, int right)
{
	int prev = left;
	int cur = left + 1;
	int keyi = left;
	while (cur <= right)
	{
		if (a[cur] < a[keyi] && ++prev != cur)
		{
			Swap(&a[cur], &a[prev]);
		}
		++cur;
	}
	Swap(&a[prev], &a[keyi]);
	keyi = prev;
	return keyi;
}
void QuickSort(int* a, int left, int right)
{
	if (left >= right)
	{
		return;
	}
	int keyi = PartSort3(a, left, right);
	QuickSort(a, left, keyi - 1);
	QuickSort(a, keyi + 1, right);
}

4.非递归

// 快速排序 非递归实现
void QuickSortNonR(int* a, int left, int right)
{
	Stack st;
	StackInit(&st);
	StackPush(&st, right);
	StackPush(&st, left);
	while (!StackEmpty(&st))
	{
		int begin = StackTop(&st);
		StackPop(&st);
		int end = StackTop(&st);
		StackPop(&st);
		int keyi = PartSort3(a, begin, end);
		if (keyi + 1 < end)
		{
			StackPush(&st, end);
			StackPush(&st, keyi + 1);
		}
		if (begin < keyi - 1)
		{
			StackPush(&st, keyi - 1);
			StackPush(&st, begin);
		}
	}


	StackDestroy(&st);
}

快速排序的特性总结

  1. 快速排序整体的综合性能和使用场景都是比较好的,所以才敢叫快速排序
  2. 时间复杂度:O(N*logN)
  3. 空间复杂度:O(logN)
  4. 稳定性:不稳定
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值