插入排序的基本思想:以插入的方式寻找元素的适当位置,以达到排序的目的。
实现过程:以升序排序为例,对n个元素的数组arr,在每次判断时,将待排数组看成一个有序表和一个无序表。第一次排序时,有序表只有1个元素,即第一个元素,无序表有n-1个元素,在排序时,每次从无序表中取出第一个元素,将其依次与有序表中的元素进行比较,并按顺序插入到适当位置,当无序表里的数据都有序插入到有序表中时,可以最终得到一个有序表。
下面针对4个元素进行插入排序的过程分析。
public static void main(String[] args) {
//假定{101,34,119,1}
int[] arr = {101, 34, 119, 1};
insertSort(arr);
}
public static void insertSort(int[] arr) {
//先逐步分析
//第1轮 {101,34,119,1}--> {34,101,119,1} 即:将34插入到101的合适位置
//定义待插入的数
int insertValue = arr[1];
int insertIndex = 1 - 1;//和前面的这数 进行比较插入
//给insertValue找到要插入的位置
//insertIndex >= 0保证在找位置时,不越界
//insertValue < arr[insertIndex]表示待插入的数字还没有找到插入的位置
//需要将arr[insertIndex]后移
while (insertIndex >= 0 && insertValue < arr[insertIndex]) {
arr[insertIndex + 1] = arr[insertIndex];
insertIndex--;//进行前一个继续比较
}
//退出循环,插入位置找到了
arr[insertIndex + 1] = insertValue;
System.out.println("====第1轮插入结果============");
System.out.println(Arrays.toString(arr));
//第2轮
//定义待插入的数
insertValue = arr[2];
insertIndex = 2 - 1;//和前面的这数 进行比较插入
//给insertValue找到要插入的位置
//insertIndex >= 0保证在找位置时,不越界
//insertValue < arr[insertIndex]表示待插入的数字还没有找到插入的位置
//需要将arr[insertIndex]后移
while (insertIndex >= 0 && insertValue < arr[insertIndex]) {
arr[insertIndex + 1] = arr[insertIndex];
insertIndex--;//进行前一个继续比较
}
//退出循环,插入位置找到了
arr[insertIndex + 1] = insertValue;
System.out.println("====第2轮插入结果============");
System.out.println(Arrays.toString(arr));
//第3轮
//定义待插入的数
insertValue = arr[3];
insertIndex = 3 - 1;//和前面的这数 进行比较插入
//给insertValue找到要插入的位置
//insertIndex >= 0保证在找位置时,不越界
//insertValue < arr[insertIndex]表示待插入的数字还没有找到插入的位置
//需要将arr[insertIndex]后移
while (insertIndex >= 0 && insertValue < arr[insertIndex]) {
arr[insertIndex + 1] = arr[insertIndex];
insertIndex--;//进行前一个继续比较
}
//退出循环,插入位置找到了
arr[insertIndex + 1] = insertValue;
System.out.println("====第3轮插入结果============");
System.out.println(Arrays.toString(arr));
通过上述代码分析可以知道:4个元素需要进行3轮插入排序,每轮的插入思路都一样,即:假定当前元素中,后一个元素为要插入的值,将其与前面所有元素进行比较,循环遍历前面每个元素,若其小于前面的元素,则将前面元素后移赋值,循环结束后,即找到插入位置,将待插入的值赋给索引号处即可。
通过循环实现的代码:
//代码循环简化
//定义待插入的数
for (int i = 1; i < arr.length; i++) {
int insertValue = arr[i];
int insertIndex = i - 1;//和前面的这数 进行比较插入
//给insertValue找到要插入的位置
//insertIndex >= 0保证在找位置时,不越界
//insertValue < arr[insertIndex]表示待插入的数字还没有找到插入的位置
//需要将arr[insertIndex]后移
while (insertIndex >= 0 && insertValue < arr[insertIndex]) {
arr[insertIndex + 1] = arr[insertIndex];
insertIndex--;//进行前一个继续比较
}
//退出循环,插入位置找到了
arr[insertIndex + 1] = insertValue;
System.out.println("====第" + (i) + "轮插入结果============");
System.out.println(Arrays.toString(arr));
}
为了逻辑更严谨,可以在while循环结束后,加一个判断,看看是否需要重新赋值,因为,如果顺序本来就是顺序状态,则不需要重新赋值。改变的代码如下:
//加一个判断,看看是否需要赋值,如果顺序本来就不用变,则不用插入赋值
if(insertIndex + 1 == i) {
arr[insertIndex + 1] = insertValue;
}
上面就是直接插入排序的思想和基本代码实现~
两层循环,因此时间复杂度是O(n^2)