重玩快排

来源:互联网 发布:网络拓扑结构选用线缆 编辑:程序博客网 时间:2024/05/22 08:01

快速排序:

简化的中值排序;

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

#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;}//#改进版qsortvoid 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);            //比较函数-intint compare_char(const void* a,const void *b);           //比较函数-charint 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//intint compare_int(const void* a,const void *b){return *(int *)a-*(int *)b;}//charint 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);//charchar 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;}


原创粉丝点击