已有的排序方法往往不能很好的满足在实际开发中的所有需求,因此需要不断探索去发现更高效的方法。
------------------------
为什么要出现选择排序?
前面论述了冒泡排序的思想,并通过Java进行了代码实现。我们知道在冒泡排序中,我们需要从左向右依次进行俩俩比较,且每一次比较都有需要进行交换的可能性,所以若不够幸运,一次排序将交换接近N*N次。要知道一点,交换的过程是要在内存中进行的,即数据在内存中的移动(注:Java语言不会发生位置移动,而只是进行了引用位置的交换),这个过程要比单纯的比较更应该得到使用者的关注。但对于此文中的选择排序而言,情况就大不一样了,虽然此方法也面临着比较次数接近N*N的量级,但是交换次数却能被有效的控制在N次以内。这样看来,其较冒泡排序具有很大的优越性。
思想——
从左侧索引值为index=0的位置向右进行扫描比较获取数据中的最小值,将最小值直接交换到索引值index的位置,下一次将从index++的位置进行扫描,而如果左侧将要进行比较的数就是剩余数的最小值(即arr[index]=min)将不进行交换,(也就是为什么交换次数可能小于N的原因)。
为了便于理解,我们仍然引用《Java数据结构和算法》一书中的例子进行说明:
代码实现——
import java.util.Random;
import java.util.Scanner;
public class SelectSort{
//test the bubbleSort
public static void main(String[] aegs){
Scanner sc=new Scanner(System.in);
int[] array=null;
//produce a array
ArrayUtil util=new ArrayUtil();
System.out.println("Please set array`s size:");
int size=sc.nextInt();
array=util.produce(size);
System.out.println("Before sort!");
util.show(array);
Sort s=new Sort(array);
array=s.sortArray();
//show sorted array
System.out.println("After sort!");
util.show(array);
System.out.format("compairsion_times:%d--exchange_times:%d",s.getComparisiontimes(),s.getExchangetimes());
}
}
class Sort{
private int[] arr=null;
private int EXCHANGE_TIMES=0;
private int COMPIRASION_TIMES=0;
public Sort(int[] array){
arr=array;
}
//selectSort(进行选择排序)
public int[] sortArray(){
//this array is not empty
if(arr!=null&&arr.length>0){
//sort array
for(int i=0;i<arr.length-1;i++){
int minNum=arr[i]; //default minNum is arr[i]
int index=0; //minNum`s index
for(int j=i+1;j<arr.length;j++){
COMPIRASION_TIMES++;
if(minNum>arr[j]){
minNum=arr[j];
index=j;
}
}
//swap number(if arr[i] is minNum ,will not need swap)
if(minNum!=arr[i]){
arr[index]=arr[i];
arr[i]=minNum;
EXCHANGE_TIMES++;
}
}
return arr;
}else{
return null;
}
}
//get exchange times
public int getExchangetimes(){
return EXCHANGE_TIMES;
}
//get comparision times
public int getComparisiontimes(){
return COMPIRASION_TIMES;
}
}
//tool class
class ArrayUtil{
private int[] arr=null;
//make a array
public int[] produce(int num){
Random rand=new Random(500);
arr=new int[num];
for(int i=0;i<num;i++){
arr[i]=rand.nextInt(100);
}
return arr;
}
//show array
public void show(int[] array){
if(array!=null){
for(int a:array){
if(a==array[array.length-1]){
System.out.format("%d\n",a);
}else{
System.out.format("%d->",a);
}
}
}
}
}
运行结果:
与冒泡排序对比——
冒泡排序结果:
从俩个实验结果中可以清楚看到俩种排序方法在数据相同的情况下,选择排序的交换次数明显少于冒泡排序。那么究竟这个因素是否会影响运行效率呢?我们在ArrayUtil类中添加如下方法,并修改main方法来获得运行时间进行对比:
//get run time(ArrayUtil中添加此方法以获取当前时间)
public long getRuntime(){
return System.currentTimeMillis();
}
long beginTime=util.getRuntime();//排序开始时间
array=s.sortArray();
long endTime=util.getRuntime();//排序结束时间
System.out.format("Runtime----%ds",(endTime-beginTime));//排序花费时间
测试结果(采用个数相同的同一组数据进行比较):
数据个数 | 冒泡交换次数 | 选择交换次数 | 冒泡排序用时(s) | 选择排序用时(s) |
10 | 36 | 6 | 0 | 0 |
100 | 2615 | 97 | 0 | 0 |
1000 | 253631 | 980 | 6 | 4 |
10000 | 25120656 | 9888 | 139 | 90 |