我们看这样一个数组:array={12,23,9,24,15,3,18}如何按从小到大顺序用选择排序算法实现??
我们用插入排序算法的思维先选择排序的过程:
先从数组中依次选出一个假定最小数,然后依次和后面的数比较大小,记录下实际最小数的下标,并在一趟比较完之后,将假定最小数和实际最小数调换位子!
我们注意到在比较过程中,我们要先选定“假定最小数”,再拿这个假定的比较数和后面没有排序的数比较,得出实际最小数!
注意这里:第一趟:我们先选“假定最小数”, 选完后依次比较--------这里就涉及到会有几趟,每趟会比较几次的问题;
我们将问题用实际例子画个流程图出来:
拿数组array:我们先定义每趟的假定最小值的下标是minIndex,最小值是min
index—> 0 1 2 3 4 5 6
array={12,23,9,24,15,3,18}
第一趟:minIndex=0 ,index=12
第1次比较:<0,1>比较(指数组下标对应的值)
minIndex=0 ,min=12
第2次比较:<0,2>
minIndex=0 ,min=12
第3次比较:<0,3>
minIndex=0 ,min=12
第4次比较:<0,4>
minIndex=0 ,min=12
第5次比较:<0,5>
minIndex=5 ,min=3
第6次比较:<5,6>
minIndex=5 ,min=3 index——>0 1 2 3 4 5 6
第一趟比较的结果:假定最小值的下标是0 ,实际最小值的下标是5,两者交换值: array={3,23,9,24,15,12,18}
第二趟:minIndex=1 ,index=23
第1次比较:<1,2>比较(指数组下标对应的值)
minIndex=2 ,min=9
第2次比较:<2,3>
minIndex=2 ,min=9
第3次比较:<2,4>
minIndex=2 ,min=9
第4次比较:<2,5>
minIndex=2 ,min=9
第5次比较:<2,6>
minIndex=2 ,min=9
第二趟比较的结果:假定最小值的下标是1 ,实际最小值的下标是2,两者交换值: array={3,9,23,24,15,12,18}
就这样一直比较直到结果出现:[3, 9, 12, 15, 18, 23, 24]
我们可以看出:
1.比较的趟数时array.length-1
2.每次取无须数组的第一个数作为假定的最小值,它的比较次数是剩余数组形成的无序数组的length-1
3.那么比较趟数i和内部比较次数j的关系: j=len-i(假设i从1开始)
根据这个可以得到程序:(注意:后来证明字体大的部分逻辑是错误的,因为对于子无序数组而言,假定最小值就是是实际最小值时,后面的数组排序不一定是排序好的)为什么在代码中红色显示不了呢??
/**选择排序思想:每次从无序序列中选择第一个数为假定最小值,依次后后面的数比较,存在更小的数,与其交换位置 * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub int array[]={12,23,9,24,15,3,18}; int len=array.length; //外层控制趟数 7-1=6趟 for(int i=1;i<=len-1;i++) { int minIndex=i-1; int min=array[minIndex]; boolean flag=false; //在i趟时,是否存在比假定最小数更小的数存在 boolean boolNoSmall=false; //标记值:判断假定最小数是否是在这一趟中的实际最小数,如果是,那么后面的循环就不用了 //内层控制比较次数 剩下几个数就比较len-1次 for(int j=len-i;j>=1;j--) { boolNoSmall=false; if(array[len-j]<min) { minIndex=len-j; min=array[minIndex]; flag=true; //假定最小数不是实际最小数,标志值 } if(minIndex==(i-1)) //假定最小值就是实际最小值,数组已经排序好 boolNoSmall=true; } if(boolNoSmall) //假定最小值就是实际最小值,数组已经排序好 break; if(flag) //假定错误,交换两个数 { int temp=array[i-1]; array[i-1]=min; array[minIndex]=temp; } } System.out.println(Arrays.toString(array)); }
注意程序上方红色部分是对程序的优化:
上方的程序是从i=1开始计数,也就是程序的趟数(第1趟。。。。。)开始。平时我们还是应该从数组的对应下标开始计数更加符合实际情况,但是我们为了便于理解,这样写也ok啦
正确的算法
public static void sort() { int array[]={1,12,23,9,24,15,3,18}; int len=array.length; int minIndex,min; //定义每次的假定最小值和最小坐标 //外层循环控制趟数:0———len-1即(0——5) for(int i=0;i<len-1;i++) { minIndex=i; min=array[minIndex]; //初始化每次的假定最小值和最小坐标 boolean flag=false; //假定最小值是否存在比其更小的数 //开始第i+1趟 //内部循环控制每趟比较的次数 //每次都得比较 len-i-1,每次比较至少比较1次(j>=1) for(int j=len-i-1;j>=1;j--) { if(array[len-j]<array[minIndex]) //存在比其更小的数 { minIndex=len-j; flag=true; } } if(flag) //交换数据 { int temp=array[minIndex]; array[minIndex]=array[i]; array[i]=temp; } } System.out.println(Arrays.toString(array)); }
给个更快的算法
public static void sort2() { int array[]={1,12,23,9,24,15,3,18}; int min; int len=array.length; for(int i=0;i<len-1;i++) //从0开始 { min=array[i]; for(int j=i+1;j<len;j++) //从i+1开始和i比较, { if(array[j]<array[i]) { min=array[j]; } if(!(min==array[i])) //直接交换 { int temp=array[i]; array[i]=array[j]; array[j]=temp; } } } System.out.println(Arrays.toString(array)); }