快速排序

快速排序

将一串数组分成四部分,有一个主元x,x的左边都比x小,x的右边都比x大。一开始选择数组的最后一个数作为主元x,然后以i记录比主元小的部分,以j记录比主元大的部分,还有一个主元部分,剩下是还未扫描到的部分。
(黄色为大于主元的子数组)
i,p,j                               r
| 2 | 8 | 7 | 1 | 3 | 5 | 6 | 4 |

| 2 | 8 | 7 | 1 | 3 | 5 | 6 | 4 |

| 2 | 8 | 7 | 1 | 3 | 5 | 6 | 4 |

| 2 | 8 | 7 | 1 | 3 | 5 | 6 | 4 |

| 2 | 1 | 7 | 8 | 3 | 5 | 6 | 4 |

| 2 | 1 | 3 | 8 | 7 | 5 | 6 | 4 |

| 2 | 1 | 3 | 8 | 7 | 5 | 6 | 4 |

| 2 | 1 | 3 | 8 | 7 | 5 | 6 | 4 |

| 2 | 1 | 3 | 4 | 8 | 7 | 5 | 6 |

找出主元并将数组分两边

int Partition(int a[],int p,int r){//设置一个主元,将数组分成两边,左边都小于主元,右边都大于主元 
	int x = a[r];//将最后一个数设为主元 
	int i = p - 1;
	int j;
	for(j=p;j<r;j++){//往后扫描数组(扩大大于大于主元的数组)
		if(a[j] <= x){//如果所扫描到的值属于左边(小于主元)
			i += 1;//扩大左边(小于主元)的数组 
			exchange(a,i,j);//将扫描到的值放进左边数组。 
		}
	}
	exchange(a,i+1,r);//将主元放到两个数组中间 
	return i+1;
}

快排

void QuickSort(int a[],int p,int r){
	if(p<r){
		int q = Partition(a,p,r);
		QuickSort(a,p,q-1);
		QuickSort(a,q+1,r);
	}
}

还有一个随机版快排,即在数组 A[p…r]中随机选择一个数作为主元。因为如果快排划分不平衡,那它的性能就接近插入排序,若主元是随机的,那在平均情况下对数组的划分是比较平衡的。

int Random_Partition(int a[],int p,int r){//在数组中随机选一个数作为主元 
	int i = Random(p,r);
	exchange(a,r,i);
	return Partition(a,p,r);
}
void Random_QuickSort(int a[],int p,int r){
	if(p<r){
		int q = Random_Partition(a,p,r);
		Random_QuickSort(a,p,q-1);
		Random_QuickSort(a,q+1,r);
	}
}

接下来是完整源码:

#include <stdio.h>
#include <time.h>

int Random(int a,int b){//在a,b(连续)之间产生一个随机数 
	srand((int)time(NULL));
	return rand()%(b-a+1)+a;
}

void exchange(int a[],int m,int n){//交换数组里的两个数 
	int tmp;
	tmp = a[m];
	a[m] = a[n];
	a[n] = tmp;
} 

int Partition(int a[],int p,int r){//设置一个主元,将数组分成两边,左边都小于主元,右边都大于主元 
	int x = a[r];//将最后一个数设为主元 
	int i = p - 1;
	int j;
	for(j=p;j<r;j++){//往后扫描数组(扩大大于大于主元的数组)
		if(a[j] <= x){//如果所扫描到的值属于左边(小于主元)
			i += 1;//扩大左边(小于主元)的数组 
			exchange(a,i,j);//将扫描到的值放进左边数组。 
		}
	}
	exchange(a,i+1,r);//将主元放到两个数组中间 
	return i+1;
}

void QuickSort(int a[],int p,int r){
	if(p<r){
		int q = Partition(a,p,r);
		QuickSort(a,p,q-1);
		QuickSort(a,q+1,r);
	}
}

int Random_Partition(int a[],int p,int r){//在数组中随机选一个数作为主元 
	int i = Random(p,r);
	exchange(a,r,i);
	return Partition(a,p,r);
}

void Random_QuickSort(int a[],int p,int r){
	if(p<r){
		int q = Random_Partition(a,p,r);
		Random_QuickSort(a,p,q-1);
		Random_QuickSort(a,q+1,r);
	}
}


int main(){
	int a[8] = {2,8,7,1,3,5,6,4};
	int length = sizeof(a)/sizeof(int);
	int i;
	for(i=0;i<length;i++){
		printf("a[%d]=%d ",i,a[i]);
	}
//	QuickSort(a,0,length-1);
	Random_QuickSort(a,0,length-1);
	printf("\n");
	for(i=0;i<length;i++){
		printf("a[%d]=%d ",i,a[i]);
	}
	return 0;
}

参考:《算法导论》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值