算法笔记之快速排序

快排也是属于分治法的一种,它的具体思想是从要排序的序列中选择一个基准也叫枢轴,把比基准小的排在一边,把比基准大的排在一边,然后以基准为界限将序列分为左右两个子序列,然后递归地对每个序列进行同样地操作,直到序列内元素为1。当递归结束时,此时主序列已被排好了序,并且相较于归并排序不需要额外地内存空间,但是缺点是不够稳定,排序的速度取决于基准的选择,并且最好情况和最坏情况相差比较大。
最好情况:T(n)=(nlogn),平均情况:T(n)=(nlogn),最坏情况:T(n)=(n*n)。
快排的具体步骤如下:
1.选择基准;
2.按照基准将序列分为两个部分;
3.递归的进行1和2直到子序列元素为1;
而如何快速的将序列按照基准分成两个部分呢?一般的话,采用两个指针来进行这一操作。指针i从序列首开始,指针j从序列尾开始。指针i记录从序列头开始的第一个比基准值大的值,指针j记录从序列尾开始的第一个比基准值小的值,然后交换i和j的值重复这个操作直到i=j。为了保证当i=j时第i个位置的数值肯定比基准值要小,我们先让j开始递减(反之则先让i递减),交换基准值和i的位置。这样我们就将所有小于基准值的数据放到了最左边,大于基准值的放到了右边。
快排的动图演示(源自大佬的博客:(算法总结(2)——温习十大经典排序算法-一杯温酒):


上面说过,基准的选择将很大部分上决定整个算法的速度,一般来说偷懒的做法是一直选择第一个元素作为基准,但是这样对于一些数据来说时间复杂度很高,那么如何进行优化呢?答案是随机选择一个基准进行排序,虽然这样仍不能避免最坏的情况的发生,但至少保证了可能会有最好情况的发生。
直接上代码:

#include<stdio.h>
#include<stdlib.h>
void swap(int * a,int i,int j){
	int temp=a[i];
	a[i]=a[j];
	a[j]=temp;
}
void quicksort(int * a,int start,int end){
	if(start<end){
		int i=start,j=end;
		int priov=(start+end)/2;//随机一个基准点 
		swap(a,start,priov);
		int standard=a[start];
		while(i<j){
			while(i<j&&a[j]>=standard){//使用i和j两个指针进行拆分操作 
				j--;
			}
			while(i<j&&a[i]<=standard){
				i++;
			}
			swap(a,i,((i==j)?start:j));
		}
		quicksort(a,start,i-1);//将已选择的基准值撇开,对子序列进行递归操作 
		quicksort(a,i+1,end);
	}
}
int main(){
	int * a,i,n;
	float p;
	scanf("%d",&n);//输入序列的个数 
	a=(int *)malloc(sizeof(int)*n);
	srand(time(0));
	for(i=0;i<n;i++){ //用于生成随机测试数据 
		p=(float)rand()/RAND_MAX;
		p=p*1000+10;
		a[i]=p;
	}
	quicksort(a,0,n-1);
	for(i=0;i<n;i++)printf("%d ",a[i]);
}  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值