目录
今天介绍的是插入排序,那插入排序跟选择排序是有点比较像的,它们都是将一个数据划分为两个部分,一个是已排序,一个是未排序,那这个是它们的相同点,当然实现上还是有很大的不一样哈,接下来我们就进入今天插入排序学习吧。
选择排序的文章:https://blog.csdn.net/weixin_53041251/article/details/123054092
1、算法描述
- 将数组分为两个区域,排序区域和未排序区域,每一轮从未排序区域中取出第一个元素,插入到排序区域(需保证顺序) 。
- 重复以上步骤,直到整个数组有序 。
2、算法演示
这里有一个无序数组。
插入排序。它首先会把索引 0 (9) 的这个位置,视为已排序的部分,那从索引 1 (3)开始的部分就都是未排序的部分,那我们的思路就是,不断扩大有序的区域,缩短无序的区域。
刚开始我们的有序区只有一个元素,那我们就把有序区扩充两个元素,这个时候它就会将 3 这个元素所在位置给它空出来,空出来的目的,就是看看把 3 放在哪个合适的位置,能够保证前面的这些元素仍然有序。
那显然,把 9 往后移动一下 ,然后将3 放在9 的位置上,这样就能保证, 索引 0 和 索引 1 区域的元素顺序是一致的,这样第一轮插入排序就完成了,接下来我们再演示一个。
接下来,我们有序的区域又扩大了,那7的位置是不是就要空出来,然后将 7 和前面的元素进行比较,看看 7 能放到什么位置,保证 索引 0 和 索引 1 和 索引 3 的元素有序。
很显然,9往后移动,那 3 就不用 移动了,因为 7 比 三 大嘛。
这样 , 索引 0 ,1 ,2 都是有序的了,接下来就是重复以上步骤直到数组有序为止。
那这样,我们的插入排序就走完了。
插入排序相对选择排序,它的优点还是不少的,
1、首先,它是一个稳定排序算法,选择排序是一个不稳定排序算法。
2、其次就是,插入排序它的性能上其实要略高于选择排序(大部分情况下)。
3、最后就是插入排序和冒泡排序的共同点,它们都是对已排序的数组,有更高效的排序效率。
比如,你看
这个数组它已经是有序的了,那把这个2 拿出来,它发现,它比1 大 ,那它岂不是就不要动,它比前面的 1 大 ,所以它两仍然是有序的,所以只比较了一次。
那接下来 3 跟 2 比,3 比 2 大 ,那也就是也比 2前面的要大,所以也放在原来的位置,这也只比较了一次。
所以根据这个规律,以此类推。
3、 算法实现
/**
* @description: 插入排序算法实现
* @author: jie
* @time: 2022/6/19 14:37
*/
public class Inser {
public static void main(String[] args) {
// 准备一个 无序的数组
int[] ints = {9, 1, 3, 3, 5, 4, 6, 8, 7, 2};
// 调用排序方法
insert(ints);
}
/**
* @description: 排序方法
* @author: jie
* @time: 2022/6/19 14:40
*/
static void insert(int[] ints) {
// i 代表插入元素的一个索引
for (int i = 1; i < ints.length; i++) {
// 声明一个临时变量 ,用来存储我们待插入的值
int t = ints[i];
// 已排序区域的元素索引的值
int j = i - 1;
while (j >= 0) {
// j 是上一个元素索引,如果 > t,后移
if (t <= ints[j]) {
ints[j + 1] = ints[j];
} else {
// // 如果 j 已经 <= t, 则 j 就是插入位置,退出循环,减少比较的次数。
break;
}
j--;
}
ints[j + 1] = t;
// 打印
System.out.println(Arrays.toString(ints));
}
}
}
效果:
4、总结
4.1 描述(已升序为例)
- 将数组分为两个区域,排序区域和未排序区域,每一轮从未排序区域中取出第一个元素,插入到排序区域。
- 重复以上步骤,知道数组有序。
4.2 优化方式
- 待插入元素进行比较时,遇到比自己小的元素,就代表找到了插入 位置,无需进行后续比较。
- 插入时直接移动元素,而不是交换元素。
插入排序通常被同学们所轻视,其实它的地位非常重要。小数据量排序,都会优先选择插入排序