排序,是作为Java算法学习过程中,不可避免的重要知识点。对于大多数的程序员来说,掌握1-2种即可,如最常用的冒泡排序等,本文讲解另外两种排序:选择排序与插入排序。
1,选择排序
定义:对于长度为N的数组,我们第一次从(0,N-1)找到最小值,将最小值所在位下标同0下标交换,这样确定了首位为最小值,再从(1,N-1)找第二最小值,再交换下标为1的数字,这样确定了第二位位置为第二最小值,依次循环,直到(N-2,N-1)时,该数组已经排好序。
比如给出一个数组Array
int[] Array = {2,1,4,3,5,7}
该数组对应的下标分别表示为 : 0 1 2 3 4 5
选择排序的思路就是,先从下标 0 ~ 5 找最小值,然后与 下标0的数字比较
===> 比如Array中,0~5下标区间内,最小值为1,1所在的下标为1,与下标0的数2交换,
Array = {2,1,4,3,5,7} ====> Array = {1,2,4,3,5,7}
同样的,我们接着进行 从下标 1 ~ 5 找最小值,然后与下标 1 的数字比较
===> 比如Array中,1~5下标区间内,最小值为2,2所在的下标为1,不用交换
继续比较,从下标 2 ~ 5 找最小值,然后与下标 2 的数字比较
===> 比如Array中,2~5下标区间内,最小值为3,3所在的下标为3,要与下标 2 的数字交换
Array = {2,1,4,3,5,7} ====> Array = {1,2,3,4,5,7}
以此类推,即可达到整个数组按从小到大进行排序
当Array = {1,2,3,4,5,7}时,选择排序完成
了解上述思想后,我们用Java代码实现:
public static void selectSort(int[] arr){
// ||--或者 &&--并且
// 数组若为空 或 数组 只有一个数字, 则不用排序
if (arr == null || arr.length<2){
return;
}
int N = arr.length;
//0-N-1 1-N-1 2-N-1
for (int i=0 ;i<N;i++){
int minValueIndex = i ;
for (int j= i+1; j <N ;j++){ //i往后所有数同i比较,如果小则取j,否则取minValueIndex
minValueIndex = arr[j] <arr[minValueIndex] ? j : minValueIndex ;
}
swap(arr,i,minValueIndex); //交换
}
}
//交换
public static void swap(int []arr , int i , int j){
int tmp = arr[i];
arr[j] = arr[i];
arr[i]= tmp;
}
2,插入排序
定义:对于一个长度为N的数组,先确定 下标从0-1有序,如果后面的数字比前面的小,则交换,交换后再与前面的数比较,直到前面没有数了,则停止,依次进行0-2,0-3,...,0-N-1上有序。
//比如说对于数组Array
int[] Array = {3,4,1,5,6,2}
对应的下标表示:0 1 2 3 4 5
插入排序的一个思想就是:
先从下标 0 ~ 1 区间内确保有序,也就是说,Array内,0 ~ 1是 3和4,本身有序不用管
再从 0 ~ 2 区间内确保有序,Array内,0 ~ 2是 {3,4,1} 很明显,位于下标3的数比前面的小
所以需要依次交换它的值。这个过程模拟如下:
先下标3的数与下标2的数交换(因为4大于1)
Array = {3,4,1,5,6,2} ===> Array = {3,1,4,5,6,2}
此时,下标为2的数字仍然小于前一个数字,因此还要交换
Array = {3,4,1,5,6,2} ===> Array = {1,3,4,5,6,2}
这样,就确保了0 ~ 2 区间内有序
依次类推,只要确保 0 ~ N-1 区间内有序时,即
Array = {3,4,1,5,6,2} ===> Array = {1,2,3,4,5,6} 插入排序完成
了解上述思想后,我们用Java代码实现:
public static void selectSort(int[] arr){
// ||--或者 &&--并且
if (arr == null || arr.length<2){
return;
}
//0-0上有序 0-1 0-2 0-3 0-N-1
int N = arr.length;
for (int end= 1;end < N; end++){
int newNumIndex = end ;
//左边有数,而且还比我大就要交换
while (newNumIndex -1 >= 0 && arr[newNumIndex -1] > arr[newNumIndex]){
swap(arr,newNumIndex-1,newNumIndex);
newNumIndex--;
}
}
}
第一种写法,比较容易理解, 下面给出复杂度更小的写法:
public static void selectSort(int[] arr){
// ||--或者 &&--并且
if (arr == null || arr.length<2){
return;
}
//0-0上有序 0-1 0-2 0-3 0-N-1
int N = arr.length;
for (int end= 1;end < N; end++){
//pre--新数的前一个位置
for (int pre = end-1;pre >=0 && arr[pre] > arr[pre+1];pre--){
swap(arr,pre,pre+1);
}
}