冒泡排序缺点:只要前者大于后者就会发生交换,但在交换过程中并不能确定后者是否就是最小元素;在进行第二次排序时又要开始重新进行遍历,这样的无意义遍历会耗费时间。
为解决冒泡排序的缺点,引入选择排序。
选择排序:从第一个元素开始遍历数组,设定最小元素的下标minIndex=i,遇到一个较小的元素时,将该元素的下标赋给minIndex,继续遍历;如果遇到一个更小的元素时,交换元素位置。设置minIndex的原因就是为了减少无意义的数组遍历,下次排序就会从相对小的元素开始排序。如果在排序中数组是有序的,则minIndex=i(没有下标赋值和元素交换的过程)。
public class selectionSort {
private int [] array;
public selectionSort(int [] array) {
this.array=array;
}
public static void main(String[] args) {
int [] a= {3,5,2,8,0,4,7,29,11};
selectionSort ssort=new selectionSort(a);
System.out.print("未排序时的数组: ");
ssort.display();
ssort.sort();
}
//打印已排列好的数组
public void display() {
for(int i=0;i<array.length;i++) {
System.out.print(array[i]+"\t");
}
System.out.println();
}
public void sort() {
int len=array.length;
int minIndex; //存储最小元素的下标
int temp; //中间数
int count=1; //交换次数
for(int i=0;i<len;i++) {
minIndex=i;
for(int j=i+1;j<len-i;j++) { //每次遍历数组,确定一个相对最小元素,下次排序只对相对小元素后面的元素排序
if(array[minIndex]>array[j]) { //如果当前元素大于某元素,将该元素下标赋给minIndex
minIndex=j; //如果有序,则minIndex=i一直
}
}
if(minIndex!=i) { //找到更小的元素,交换位置
temp=array[i]; //交换
array[i]=array[minIndex];
array[minIndex]=temp;
}
System.out.print("第"+count+"次排序结果");
display();
count++;
}
}
}
代码优化:每次排序确定最大值与最小值,可以将排序次数减半。
public void sort() {
int len=array.length;
int minIndex; //存储最小元素的下标
int maxIndex; //存储最大元素的下标
int temp; //中间数
int count=1; //交换次数
for(int i=0;i<len/2;i++) {
minIndex=i;
maxIndex=i;
for(int j=i+1;j<len-i-1;j++) { //确定最大值和最小值,下次排序时就减少两个元素
if(array[minIndex]>array[j]) { //如果当前元素大于某元素,将该元素下标赋给minIndex
minIndex=j;
}
else if(array[maxIndex]<array[j]) {//如果当前元素小于某元素,将该元素下标赋给minIndex
maxIndex=j;
}
}
if(minIndex!=i) { //找到更小的元素,交换位置
temp=array[i];
array[i]=array[minIndex];
array[minIndex]=temp;
//此时,原来第一个元素已与minIndex指向的元素交换了位置,
//而交换后的minIndex指向的元素一定比第一个元素小,
//也就是说比maxIndex指向的元素小,所以要把minIndex赋给maxIndex
if(maxIndex==i) {
maxIndex=minIndex;
}
}
if(maxIndex!=len-i-1) { //找到更大的元素,交换位置
temp=array[len-i-1];
array[len-i-1]=array[maxIndex];
array[maxIndex]=temp;
}
System.out.print("第"+count+"次排序结果");
display();
count++;
}
}
测试结果: