快速排序(含图解)

简称快排,是对冒泡排序的一种改进,基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。




实现原理及过程(含图解)

比如我们对 “8,9,1,3,5,2,7,6” 这组数据进行排序,首先我们随便找一个数作为参照数称为支点,然后想办法的让比支点小的数堆在左边,让比支点大的数堆在右边,以此来分成两部分,再对余下两边使用快速排序即可。



首先,选取支点,用 i 指着数组最左边,用 j 指着数组最右边,要使支点的左边小于等于5,右边大于等于5,就要让 i 往右移比较,让 j 往左移比较,直至 i 与 j 交叉错开即可保证左边都小于支点,右边都大于支点 (如下图)

在这里插入图片描述

让 i 和 j 移动过程中与支点比较,如果a[ i ]大于支点,a[ j ]小于支点,两者交换,否则 i 、j 继续移动。

(如:一开始a[0]大于5,那么 i 先停止移动,a[ j ]由于大于5,j左移,直到a[5]时小于支点,那么a[0]与a[5]的值进行交换,然后 i 、j 再进行移动直至错开。)


交换第一次后:
在这里插入图片描述
循环上述步骤直至错开

最终错开时:
在这里插入图片描述
至此,从a[0]到a [ j ] 的数都小于等于5,从a[ i ]到a [7] 的数都大于等于5,我们完成了第一步,接下来就分别让左边和右边再进行快速排序即可。


因此我们可以用递归来做,所以我们要考虑递归出口条件:
即 数组元素下标 < j ,左边需进行快速排序;
即 数组元素下标 > i ,右边需进行快速排序;

代码:
#include <iostream>
using namespace std;
void quicksort(int a[],int left, int right)
{
	int i,j,point,t;
	point = a[(left+right)/2];
	i = left;
	j = right;
while(i<=j)				//i与j没错开就要继续循环
{
	while(point>a[i])
	{
		i++;
	}
	while(point<a[j])
	{
		j--;
	}
	if(i<=j)
	{
		t=a[i];
		a[i]=a[j];
		a[j]=t;
		i++;
		j--;
	}
}	
	if(left<j)
	quicksort(a,left,j);
	if(i<right)
	quicksort(a,i,right);
} 
int main()
{
	int a[8]={8,9,1,4,3,5,7,6},i;
	i=8;
	quicksort(a,0,i-1);
	
	for(i=0;i<8;i++)
	cout<<a[i]<<endl;
	return 0;
}
时间复杂度:O(NlogN)

快速排序相比于冒泡排序,每次交换是跳跃式的。每次排序的时候设置一个支点,将小于等于支点的数放到支点的左边,将大于等于支点的数放到支点的右边。这样在每次交换的时候就不会像冒泡排序一样只能在相邻的数之间进行交换,交换的距离就大得多了。因此总的比较和交换次数就少了,速度自然就提高了。当然在最坏的情况下,仍可能是相邻的两个数进行了交换。因此快速排序的最坏时间复杂度和冒泡排序是一样的都是O(N2),但它的平均时间复杂度为O(NlogN)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值