我们常用的十大排序算法:选择排序、冒泡排序、插入排序、堆排序、希尔排序 、归并排序、快速排序、桶排序、计数排序、基数排序。
今天实现的是选择排序的算法。
package com.jandmin.demo.leetcode.sort;
import java.util.Random;
/**
* @description: 排序算法:
* 用第一个位置的数依次和后面每一个位置的数比较,把小的拿出来再继续往后比较,
* 这样一轮下来就能得到做小值的位置,然后把最小值的位置和第一个位置数字互换;
* 接着拿第二个位置的数...
*
* @author: JandMin
**/
public class SortAlgorithm {
private static int countInner1 = 0;
private static int countOut1 = 0;
private static int countInner2 = 0;
private static int countOut2 = 0;
private static int countInner3 = 0;
private static int countOut3 = 0;
private static int countInner4 = 0;
private static int countOut4 = 0;
/**
* 初始化数组
* @param len 数组长度
* @return
*/
private static int[] initArray(int len){
if(len < 0){
return new int[0];
}
int[] array = new int[len];
Random random = new Random(len);
for(int i=0; i<len; i++){
array[i] = random.nextInt(len);
}
// System.out.println("数组 --> "+JSONObject.toJSONString(array));
return array;
}
public static void main(String[] args) {
int len = 10000;
int[] array = initArray(len);
// 方案1
int[] array1 = array.clone();
long start = System.currentTimeMillis();
selectMin(array1);
// System.out.print("排序1--> "+ JSONObject.toJSONString(array1));
System.out.println(" 1耗时:"+(System.currentTimeMillis()-start)+" ms,countInner:"+countInner1+",countOut:"+countOut1);
// 方案2
int[] array2 = array.clone();
start = System.currentTimeMillis();
selectMinTwo(array2);
// System.out.print("排序2--> "+JSONObject.toJSONString(array2));
System.out.println(" 2耗时:"+(System.currentTimeMillis()-start)+" ms,countInner:"+countInner2+",countOut:"+countOut2);
// 方案3
int[] array3 = array.clone();
start = System.currentTimeMillis();
selectMinAndMax(array3);
// System.out.print("排序3--> "+JSONObject.toJSONString(array3));
System.out.println(" 3耗时:"+(System.currentTimeMillis()-start)+" ms,countInner:"+countInner3+",countOut:"+countOut3);
// 方案4
int[] array4 = array.clone();
start = System.currentTimeMillis();
selectMinAndMaxTwo(array4);
// System.out.print("排序4--> "+JSONObject.toJSONString(array4));
System.out.println(" 4耗时:"+(System.currentTimeMillis()-start)+" ms,countInner:"+countInner4+",countOut:"+countOut4);
}
/**
* @Description: 选择排序:遍历数组,找到最小值的位置,把最小的值放到最前面
* @param array 数组
* @return: void
*/
private static void selectMin(int[] array){
int length = array.length;
for(int i=0; i<length; i++){
countOut1++;
int minPlace = i; // 最小值下标
for (int j=i+1; j<length; j++){
countInner1++;
minPlace = array[j] < array[minPlace] ? j : minPlace;
}
exchange(array, i, minPlace);
}
}
/**
* @Description: 同时比较两个
* @Date: 2019/7/1
* @param array 数组
* @return: void
*/
private static void selectMinTwo(int[] array){
int length = array.length;
for(int i=0; i<length; i++){
countOut2++;
int minPlace = i;
for (int j=i+1; j<length-1; j=j+2){
countInner2++;
if(array[j] < array[j+1]){
minPlace = getMinIndex(array,j,minPlace);
} else {
minPlace = getMinIndex(array,j+1,minPlace);
}
}
exchange(array, i, minPlace);
}
}
/**
* @Description: 选择排序:同时获取最小值和最大值的位置,把最小值放前面,最大值放在最后面(countInner:25,countOut:5)
* @Date: 2019/6/28
* @param array 数组
* @return: void
*/
private static void selectMinAndMax(int[] array) {
int length = array.length;
for(int i=0; i<length/2; i++){
countOut3++;
int minPlace = i; // 最小值下标
int maxPlace = length-1-i; // 最大值下标
if(array[minPlace] > array[maxPlace]){ // 最大值最小值先比较,不然最后数据交叉时会出问题
exchange(array,minPlace,maxPlace);
}
for (int j=i+1; j<length-i; j++){
countInner3++;
if(array[j] < array[minPlace]){
minPlace = j;
} else if(array[j] > array[maxPlace]){
maxPlace = j;
}
}
exchange(array, i, minPlace);
exchange(array, maxPlace, length-1-i);
}
}
/**
* @Description: 寻找最小值和最大值时同时选择两个进行比较,再跟当前最大值和最小值进行比较
* @Date: 2019/7/1
* @param array 数组
* @return: void
*/
private static void selectMinAndMaxTwo(int[] array){
int length = array.length;
for(int i=0; i<length/2; i++){
countOut4++;
int minPlace = i; // 最小值下标
int maxPlace = length-1-i; // 最大值下标
if(array[minPlace] > array[maxPlace]){ // 最大值最小值先比较,不然最后数据交叉时会出问题
exchange(array,minPlace,maxPlace);
}
for (int j=i+1; j<length-2-i; j=j+2){
countInner4++;
if(array[j]<array[j+1]){
minPlace = getMinIndex(array,j,minPlace);
maxPlace = getMaxIndex(array,j+1,maxPlace);
} else {
minPlace = getMinIndex(array,j+1,minPlace);
maxPlace = getMaxIndex(array,j,maxPlace);
}
}
exchange(array, i, minPlace);
exchange(array, maxPlace, length-1-i);
}
}
/**
* @Description: 获取两个数中小数的下标
* @Date: 2019/7/2
* @param array 数组
* @param index1 下标1
* @param index2 下标2
* @return: int
*/
private static int getMinIndex(int[] array,int index1,int index2){
if(array[index1] < array[index2]){
return index1;
}
return index2;
}
/**
* @Description: 获取两个数中大数的下标
* @Date: 2019/7/2
* @param array 数组
* @param index1 下标1
* @param index2 下标2
* @return: int
*/
private static int getMaxIndex(int[] array,int index1,int index2){
if(array[index1] > array[index2]){
return index1;
}
return index2;
}
/**
* @Description: 数组两个位置上的数互换
* @Date: 2019/6/28
* @param array 数组
* @param i 小的值下标
* @param j 大的值小标
* @return: void
*/
private static void exchange(int[] array, int i, int j) {
if(i == j){
return;
}
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
执行结果:
1耗时:100 ms,countInner:49995000,countOut:10000
2耗时:139 ms,countInner:24995000,countOut:10000
3耗时:49 ms,countInner:25000000,countOut:5000
4耗时:87 ms,countInner:12497500,countOut:5000
选择排序虽然简单,但也是可以优化的。也许还有更好的优化方案,欢迎留言交流!!