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编辑  收藏  举报

导航