张仰彪选择排序法, 请大家评判一下
张仰彪选择排序法
本排序法是在选择排序法的基础上发展而来的。
选择排序法是寻找当前排序位置后边最小的一个数据,然后将此最小数据与当前排序位置上的数据进行交换,经过不断重复上述步骤,数组排序完毕。
本排序法的原理与选择排序法基本相同,但本排序法在排序时不仅寻找当前排序位置后边最小的一个数据,而且将当前排序位置后边次小的数据也顺便找出,然后将最小数据和次小数据交换到当前位置和当前位置后边第一个位置上。
这样,本排序法一次排序循环就可以排好两个数据,排序的循环次数比选择排序法少了一半,但这并不意味着本排序法的整个排序过程就可以大幅节省数据比较和交换的总次数。因为很容易知道数据交换次数在这种情况下是不应该变的,而数据比较的次数也只有在较少的情况下本排序法才会比选择排序法少。
比如,在当前排序位置后边查到一个最小数据a[x]后,如果接下来遇到的数据a[x+1]比此最小数据a[x]还小,那么就可以直接把刚才的最小数据a[x]视为次小数据而记下它的位置下标,在这种情况下就省掉了一次数据比较。只不过随着最小数据越来越小以及越查越接近数组尾部,继续遇到更小数据的可能也越来越小。
很多情况下,在当前排序位置后边查到一个最小数据a[x]后,接下来遇到的数据a[x+1]比此最小数据a[x]要大,所以它不可能成为新的最小数据,但它却可能比当前排序位置上的数据要小,从而成为新的次小数据,这就比须进行比较才能确定。依此类推,在类似这样的情况下,虽然本排序法与选择排序法相比其排序步骤少了1/2,但本排序法的每一个排序步骤内的数据交换次数都是双倍的,而数据比较次数则达不到双倍,合计起来总数有一定幅度的减少。
至于本排序法的数据比较次数究竟比选择排序法减少了多少,这涉及一个几率问题,在最好的情况下可以减少25%,在最坏的情况下可以减少0 %,正常情况下可以减少12.5 %。
例如:处理完全反序的待排序数组,当前几次排序时,由于总是可以在数组的尾部查到一个最小数据来与数组头部的大数据进行交换,所以此时由于每次循环都可以将两个小数据排好序,所以此时的数据比较次数比选择排序法少50 %。但随着当前排序位置逐渐后移,当查到最后一个最小数据时,它的后面总有多个比它大的数据,必须再将这些数据与次小数据进行比较,看它们是否小于次小数据,这就又增加了比较次数,合计起来本排序法的数据比较次数比选择排序法减少了12.5 %。
所以总的来说,本选择排序法是有一定的进步意义的。
下面给出双选择排序法的C语言代码:
-------------------------------------------------------------------------------------------------------
# include < stdio.h >
void main ( )
{
int a [10];
int i,x; /* 记录排序的次数和当前排序的位置 */
int min1, min2 ,min3; /* 记录查到的最小、次小等数据的位置 */
int temp; /* 数据交换时的存储中介 */
printf ( " Input 10 numbers:\n" );
for ( i=0;i < 10;i++ ) /* 输入任意10个整数 */
scanf ( " %d",&a[i] );
printf ( " \n" );
for ( i=0;i < =8;i +=2 ) /* 排序时一个循环向前跨两步 */
{
min1=i; min2=i+1; /* 若查不到更小的数据,最小数据就在当前位置,
将次小的初值设为i+1,是为了处理最小就是当前的特殊情况*/
for ( int x = i+1;x < =9;x ++ ) /* 查找当前位置(含)后面两个小数据 */
{
if ( a[x] < a[min1] )
{
min2=min1; /* 先将原先最小数据的下标存到min2里 */
min1=x; /* 再将新查到的最小数据的位置存到min1里 */
}
} /* 获得当前位置后边的最小和次小数据的位置*/
for(x=min1+2; x<9; x++) /* 在最小数后面的找出一个最小的*/
{ /* 因为最小数后面的数虽然都比最小大,但却可能小于次小0*/
min3=min1+1;
if(a[x]<a[min3]) min3=x;
} /*即使当前就是最小,仍可用此for( )循环找到一个次小*/
if(a[ min3] <= a[min2]) min2=min3; /* 这才是真正的次小*/
/* 之所以用<=,是尽可能把次小的位置向后定*/
if(min2!=i) /* 次小不在当前位置,先交换最小不会错移次小*/
{
temp=a[min1]; /*先交换最小到当前位置*/
a[min1]=a[i];
a[i]=temp;
temp=a[min2]; /*然后再交换次小到当前之后*/
a[min2]=a[i+1];
a[i+1]=temp;
}
else /*min2=i, 次小在当前位置上,此时先交换最小会错移次小*/
{
if(min1=i+1) /*次小在当前位置,后边第一个就是最小*/
{
temp=a[min2]; /*将次小和最小互换位置即可*/
a[min2]=a[min1];
a[min1]=temp;
}
else /*次小在当前位置,后边相隔一个以上才是最小*/
{
temp=a[min2]; /*先交换次小到当前之后*/
a[min2]=a[i+1];
a[i+1]=temp;
temp=a[min1]; /*然后再交换最小到当前位置*/
a[min1]=a[i];
a[i]=temp;
}
}
}
printf ( " The sorted numbers is:\n" );
for ( i=0;i < 10;i ++ ) /* 输出排好序的10个整数 */
printf ( " %d",a[i] );
printf ( " \n" );
}
----------------------------------------------------------------------------------------------------
< 完 >