重玩快排

10 篇文章 0 订阅

快速排序:

简化的中值排序;

我们来看看什么是中值排序:

#1对于给定的一个无序数组,我们找到它的中值,并将小于中值的数排到前面,大于中值的数排在后面。O(n) //假设找中值已经找到

#2分治:分别中值排序两边的数组;O(logN)

难点:如何选择中值

方案1:多次的partition,一次partition(随机选择一个位置作为基准),partition之后返回基准最后的位置,如果在中间偏左则往右边找基准,反之往左边找基准

经过多次partition可以找到中值(次数k=1~N),  selectK  O(KN) ---- O(N^2)

//优化

方案2:BFPRT,将原数组分为4个一组,n/4组,4个元素只需要5次即可排序,第三个元素作为基准,将n/4个基准数组的中值作为选择的中值(近似),

     由于这个中值针对原数组来说:起码有3/8小于这个中值,起码有2/8大于等于这个中值;**

     1 2 3 4 5 6 7 8 9 10 11 12

      1 2 3 4     5 6 7 8   9 10 11  12

      3,7,10,12

      10

那么每次选择的中值都相对靠近真正中值,算法趋近O(n.logN)

 

快速排序:

每次选择中值随便选一些策略(例如选第一个值,选中间按个,随机选择) 事实证明随机选择效果就比较好了,(且速度快于中值排序(不用真的中值))

#1对于给定的一个无序数组,随机选择基准,并将小于基准的数排到前面,大于基准的数排在后面。O(n) //假设找中值已经找到

由于随机选择基准,不知道最后基准在的位置,因此作如下操作:

1.1 将基准值与最后一个值交换 O(1)

1.2 遍历数组 只要遇到一个比基准小(或等)的数,就往对应位置交换(第一个比基准小的值放到第一个位置,第k个交换到第k个位置) O(n)

1.3 将基准值放到正确的位置(设有M个数比基准小,那么放到第M+1)的位置

1.4返回基准位置

#2分治:分别中值排序两边的数组;O(logN)

2.1如果小于2个元素,排好

2.2否则执行#1,得到基准

2.3快排基准左边

2.4快排基准右边

 

讨论:

A,时间复杂度:

最好           平均            最坏

O(NlogN)   O(NlogN)   O(N^2)

最坏情况是:每次partition都选择最大/最小值,一次partition只能缩小一个规模,和线性排序一致。partition要调用N-1次,每次O(N),  O(N^2)

B,稳定性:  不稳定排序

在partition过程中,我们依照数组原顺着将小于基准的值依次交换到前面,但是在之前我们将基准值移动到了最后,那么交换就是不稳定的:

例如:我们选择5(1)作为基准

9   ,7   ,   8,    5(1),  5(2),  1,  2  ,3      原数组

9   ,7   ,   8,    3,       5(2),  1,  2  ,5(1),   交换基准到右边

3  , 7   ,   8,    9 ,      5(2),  1,  2  ,5(1),   将小于基准的逐个交换到左边

3 , 5(2),  8,    9 ,     7   ,     1,  2  ,5(1),  

3 , 5(2),  1,    9 ,     7   ,     8,  2  ,5(1),  

3 , 5(2),  1,    2 ,     7  ,      8,  9  ,5(1),  

3 , 5(2),  1,    2 ,     5(1),   8,  9  ,7       注意交换最后两个5的相对位置发生了变化

只是一个例子,只要基准左右有与基准一样的值都会照成顺序不一致。

 

 

 

 

     

 

快速排序int版本

//随机选择基准(一种策略而已)
int choosePIbyRand(int l,int r){
	srand((unsigned)time( NULL));
	int pi=rand()%(r-l+1)+l;
	return pi;
}




//#改进版qsort
void myswap(int *a,int *b){
	int tmp =*a;
	*a=*b;
	*b=tmp;
}

int partition(int array[],int left,int right){
	//随机选择基准(一种策略而已)
	int pivot = choosePIbyRand(left,right);
	//将基准值转移到右侧,等确定基准的真正位置,再移回去
	myswap(&array[pivot],&array[right]);
	//凡是比基准小的元素,都移动到左边(第k个比基准小的元素,将会交换到第k个位置)
	int store=left;
	for(int i=left;i<right;i++){
		if(array[i]<=array[right]){
			myswap(&array[i],&array[store]);
			store++;
		}
	}
	//将基准移动到所有比他小元素的右边一个位置
	myswap(&array[right],&array[store]);
	return store;
}

void quickSortPro(int array[],int left, int right)
{
	if(right>left){
		int pi = partition(array,left,right);  //选择基准坐标,且保证基准左边小于基准值,基准右边大于基准值
		quickSortPro(array,left,pi-1);   //分治
		quickSortPro(array,pi+1,right);

	}	
}
void myqs(int array[],int n){
	quickSortPro(array,0,n-1);
}


 

 

 

 

快速排序通用版本,可以排序多种数据,包括结构体某字段:

//##############################################################################
//##############################################################################
//##############################################################################
//扩展版本,可以比较对象里面的字段
void xmyswap(char *a,char *b,int width);                 //通用交换函数
int compare_int(const void* a,const void *b);            //比较函数-int
int compare_char(const void* a,const void *b);           //比较函数-char
int xpartition(void* array,int left,int right,size_t size,int(* compareFunc)(const void*,const void *));          //划分
void xquickSortPro(void * array,int left, int right,size_t size,int(* compareFunc)(const void*,const void *));    //通用快排
void xmyqs(void * array,int n,size_t size,int(* compareFunc)(const void*,const void *));
//######################################################################################
//1.1 交换函数
void xmyswap(char *a,char *b,int width){
	char tmp;
	while(width--){
		tmp=*a;
		*a++=*b;
		*b++=tmp;
	}
}
//######################################################################################
//1.2比较函数
//compare(a,b) a>b >0  a<b <0 a==b =0   只看结果是否大于0
//int
int compare_int(const void* a,const void *b){
	return *(int *)a-*(int *)b;
}
//char
int compare_char(const void* a,const void *b){
	return *(char *)a-*(char *)b;
}
//结构体
struct student{
	int id;
	char *name;
	double data;
};
//
int compare_st_id(const void* a,const void *b){
	return (*(student *)a).id -  (*(student *)b).id;
}
int compare_st_data(const void* a,const void *b){
	return (*(student *)a).data >  (*(student *)b).data ? 1:-1;
}
int compare_st_name(const void* a,const void *b){
	return strcmp((*(student *)a).name , (*(student *)b).name);
}
//#################################################################################################
//1.3划分
int xpartition(void* array,int left,int right,size_t size,int(* compareFunc)(const void*,const void *)){
    int pi = choosePIbyRand(left,right);
	char *a=(char*)array+pi*size;
	char *b=(char*)array+right*size;
	xmyswap(a,b,size);
	int store=left;
	for(int i=left;i<right;i++){
		char *c=(char*)array+i*size;
		char *d=(char*)array+right*size;
		if(compareFunc(c,d) <= 0){
			a=(char*)array+i*size;
			b=(char*)array+store*size;
			xmyswap(a,b,size);
			store++;
		}
	}
	a=(char*)array+right*size;
	b=(char*)array+store*size;
	xmyswap(a,b,size);
	return store;
}
//#################################################################################################
void xquickSortPro(void * array,int left, int right,size_t size,int(* compareFunc)(const void*,const void *)){
	if(right>left){
		int pi=xpartition(array,left,right,size,compareFunc);
		xquickSortPro(array,left,pi-1,size,compareFunc);
		xquickSortPro(array,pi+1,right,size,compareFunc);
	}
}
//#################################################################################################
void xmyqs(void * array,int n,size_t size,int(* compareFunc)(const void*,const void *)){
	xquickSortPro(array,0,n-1,size,compareFunc);
}
//#################################################################################################
//打印函数
void printArray(int array[],const int n){
	for(int i=0;i<n;i++)
	{
		printf("%d ",array[i]);
	}
	printf(".\n");
}

void printCharArray(char array[],const int n){
	for(int i=0;i<n;i++)
	{
		printf("%c ",array[i]);
	}
		printf(".\n");
}

void printStudent(student array[],const int n){
	for(int i=0;i<n;i++)
	{
		printf("%d ",array[i].id);
		printf("%s ",array[i].name);	
		printf("%f",array[i].data);
		printf(".\n");
	}
	printf(".\n");

}
int main(int argc, char* argv[])
{
	int b1[]={13,12,11,10,9,2,2,2,8,7,6,5,4,3,1};
	int b2[]={13,12,11,10,9,2,2,2,8,7,6,5,4,3,1};
	int b3[]={3,2,1,5};
	int b5[]={3,2,1,5};

	//function->quickSort(b1,0,14);//算法写错了
    //function->printArray(b1,15);
    quickSortPro(b2,0,14);//算法修改
	printArray(b2,15);
//
	//通用版测试:
//int 
	int b4[]={13,12,11,10,9,2,2,2,8,7,6,5,4,3,1};
	xmyqs(b4,15,sizeof(int),compare_int);
	printArray(b4,15);
//char
	char c1[]={'e','a','f','g','p','b','c','g','o','u','x'};
	char c2[]={'c','o','e','a','f','g','p','b','g','u','x'};
	xmyqs(c1,11,sizeof(char),compare_char);
	printCharArray(c1,11);
	xmyqs(c2,11,sizeof(char),compare_char);
	printCharArray(c2,11);
//结构体
	student s0[7]={{1,"terry",90.0},{7,"marry",80.0},{2,"tom",7.0},{5,"andy",9.0},{6,"tusiki",8.5},{3,"xx",70.0},{4,"yy",55.0}};
	student s1[7]={{1,"terry",90.0},{7,"marry",80.0},{2,"tom",7.0},{5,"andy",9.0},{6,"tusiki",8.5},{3,"xx",70.0},{4,"yy",55.0}};
	student s2[7]={{1,"terry",90.0},{7,"marry",80.0},{2,"tom",7.0},{5,"andy",9.0},{6,"tusiki",8.5},{3,"xx",70.0},{4,"yy",55.0}};
	xmyqs(s0,7,sizeof(student),compare_st_id);
	xmyqs(s1,7,sizeof(student),compare_st_data);
	xmyqs(s2,7,sizeof(student),compare_st_name);
	printStudent(s0,7);
	printStudent(s1,7);
	printStudent(s2,7);
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值