对于选择排序算法,其实有很大的一个问题:在每趟的比较过程中,程序一旦发现某个数据比第一位的数据小,立即交换它们。这保证在每趟比较的所有比较过的数据中,第1位的数据永远是最小的,单着没有太大必要,反而增加了交换的次数,导致算法效率降低。
改进优化后的算法如下:
public class SelectSort { public static void selectSort(DataWrap[] data) { System.out.println("开始排序"); int length = data.length; //依次进行n-1趟比较,第i趟比较将第i大的值选出来放在i位置上 for(int i = 0;i < length-1; i++ ) { //mindex永远保存本趟比较中最小值得索引 int mindex = i; //第i个数只需要与它后面的数比较 for(int j = i+1;j < length;j++) { //如果mindex上的数据大于j位置上的数据 if(data[mindex].compareTo(data[j]) > 0) { //将j的值赋给mindex mindex = j; } } //每次比较最多交换依次 if(mindex != i) { DataWrap tep = data[i]; data[i] = data[mindex]; data[mindex] = tep; } System.out.println(java.util.Arrays.toString(data)); } } public static void main(String[] args) { DataWrap[] data = { new DataWrap(21, ""), new DataWrap(30, ""), new DataWrap(49, ""), new DataWrap(30, ""), new DataWrap(16, ""), new DataWrap(9, "") }; System.out.println("排序之前: " + java.util.Arrays.toString(data)); selectSort(data); System.out.println("排序之后: " + java.util.Arrays.toString(data)); } } class DataWrap implements Comparable<DataWrap> { int data; String flag; public DataWrap(int data, String flag) { this.data = data; this.flag = flag; } public String toString() { return data+flag; } public int compareTo(DataWrap dw) { return this.data > dw.data ? 1 : (this.data > dw.data ? 0 : -1); } }
结果图:
在这种排序规则下,每趟比较的目的只是找出本题比较中的最小数据的索引——也就是上面程序中的midIndex变量所保存的值。当本趟比较的第i位(由i变量保存)与midIndex不相等时,交换i和midIndex两处的数据。
从结果图中可以看出,直接选择排序的第n趟比较至多交换一次,永远总是拿n-1位的数据和中间某项数据(本趟比较中最小的数据)进行交流。如果本趟比较时第n-1位(本趟比较的第1位)数据已经是最小,那就无需交换。
对于直接选择排序算法而言,假设有n项数据,数据交换的次数最多有n-1次,但程序比较测次数较多,总体来说,其时间效率为O(n²)。空间效率很高,它只需要一个附加程序单元用于交换,其空间效率为O(1)。直接选择排序是不稳定的。