快速排序-原理及实现

快速排序

快速排序是一种最坏情况时间复杂度为o(n^2)的排序算法,虽然最坏情况时间复杂度很差,但是快速排序通常是实际应用中最好的选择,因为它的平均性能非常好,它的期望时间复杂度是o(nlgn),而且隐含的常数因子非常小。


一.基本思想

分解:将数组A[p..r]划分为两个子数组A[p..q-1],A[p+1..r](可能为空),使得A[p..q-1]均小于A[q],A[q+1]均大于A[q]

解决:递归调用快速排序,分别对两个字数组再进行排序

和平:因为子数组都是原址排序,所以不需要合并数组已经有序


二.代码实现

具体来说我们采用挖坑填数法,

1.i =Left; j = Right; 将基准数挖出形成第一个坑a[i]。

2.从j开始由后向前找比它小的数,找到后挖出此数填前一个坑a[i]中。

3.从i开始由前向后找比它大的数,找到后也挖出此数填到前一个坑a[j]中。

4.再重复执行2,3二步,直到i==j,将基准数填入a[i]中。

具体代码如下:

#include<iostream>

using namespace std;

int Partition(int *array,int i,int j)        //排序并返回基准数正确位置
{	
	int X=array[i];                      //设定基准数
	while(i<j)
	{
		while(i<j&&array[j]>=X)
		{
			--j;
		}
		if(array[j]<X){
			array[i]=array[j];
		}
		while(i<j&&array[i]<=X)
			++i;
		if(array[i]>X){
			
			array[j]=array[i];
		}
	}
	array[i]=X;
	return i;
}

void QuickSort(int *array,int i,int j)
{
	int p;
	if(i<j)
	{
		p=Partition(array,i,j);
		QuickSort(array,i,p-1);
		QuickSort(array,p+1,j);
	}
}



void Print(int *array, int length)
{
	for(int i=0;i<length;i++)
	{
		cout<<array[i]<<" ";
	}
	cout<<endl;
}


int main()
{
	int n,*array;
	cout<<"Please enter the number of the array: ";
	cin>>n;
	cout<<"Please enter the array now:";
	for(int i=0;i<n;++i)
	{
		cin>>array[i];
	}
	QuickSort(array,0,n-1);
	Print(array,n);
	return 0;
}

三.算法时间复杂度

快速排序的运行时间依赖于划分是否平衡,而平衡与否又依赖于用于划分的元素。如果划分是平衡的,那么快速排序算法性能与归并排序一样。如果划分是不平衡的,那么快速排序的性能就接近于插入排序了。

最坏情况划分

当划分差生的两个子问题分别包含了n-1个元素和0个元素时,快速排序的最坏情况发生。假设每一次递归调用都产生了这种不平衡的划分。划分操作的时间复杂度是O(n),由于对一个大小为0的数组进行递归调用会直接返回,因此T(0)=O(1),于是算法运行的递归表达式为T(n)=T(n-1)+T(0)+O(n)=T(n-1)+O(n)。每一层递归的代价可以被累加起来,从而得到一个算术级数,其结果为O(n^2).因此,如果在算法的每一层递归上,划分都是最大程度不平衡的,那么算法的时间复杂度就是O(n^2)。

最好情况划分

在可能的最平衡的划分中,Partition得到的两个子问题的规模都不大于n/2,这是因为其中一个子问题的规模为n/2,另一个为n/2-1,。此时算法的运行时间的递归式为T(n)=2T(n/2)+O(n),解为T(n)=O(nlgn).


快速排序的平均运行时间更接近于最好情况,任何一种常熟比例的划分都会产生深度为O(lgn)的递归数,其中每一层的时间代价都为O(n),因此,只要划分是常数比例的,算法的运行时间总是O(nlgn).

所以,快速排序算法的平均时间复杂度为O(nlgn),最坏时间复杂度为O(n^2)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值