Nico lomuto法求分界点
分界点,即该点左边的值都小于它,右边的值都大于它。
在处理过程中随便挑选一个点,令为a,这个数不一定是数组中的元素,并且让数组x[]始终满足如下关系:
L,R是数组x两端下标,j是小于a元素中最右边的脚码,第j+1个就大于等于a了,i是下一个待处理元素的脚码,因此x[j+1]到x[i-1]之间的元素都大于等于a。现在处理x[i],x[i]与a的关系无非两种:
1.x[i]>=a:因为x[i]>=a,所以大于等于a的部分可以向右延伸覆盖住x[i],如下图所示:
2.x[i]<a:此时,x[i]这个值得位置就不对,因为它小于a,应该在x[j+1]左边才是,那么怎么办呢?我们可以将x[j+1]与x[i]互换,并将i,j都往右移动一步,那么上述的关系还是不变。
按照此法,当i一直到达R,x[R]处理完之后,工作也就结束了。那么x[j]就是一个分界点。但还有一个问题,a要如何选择呢?如果把a选的都大于或者都小于数组中的元素,那么上述做法是没有意义的。因此一般做法把a选为数组中的元素,最好能把数组分成差不多长的两半,最理想的就是选a为中位数,但求中位数也是一个难题(后续将介绍如何用上述方法求一个数组的中位数)。
基于上述思想,我们很容易编出程序(选a为数组的第一个元素):
1 void split(int input[],int first,int last,int *split_point){ 2 int current_split,unknown; 3 int x; 4 x=input[first]; 5 current_split=first; 6 for(unknown=first+1;unknown<=last;unknown++){ 7 if(input[unknown]<=x){ 8 current_split++; 9 swap(&input[current_split],&input[unknown]); 10 } 11 } 12 swap(&input[first],&input[current_split]); 13 *split_point=current_split; 14 15 } 16 void swap(int *p,int *q){ 17 int tmp; 18 tmp=*p; 19 *p=*q; 20 *q=tmp; 21 }
posted on 2018-12-11 18:20 Lucifer_Rb 阅读(268) 评论(0) 编辑 收藏 举报