目录
插入排序
插入排序的核心图解
希尔排序
希尔排序详细图解
插入排序
插入排序的交换精髓在于 每次随着i的扩大,i走过的路径都是有序的,这和冒泡的思想有异曲同工之处,冒泡是i走一次,数组的最后变成有序的,而插入排序是
插入排序是 i 在前面 j在后面
插入排序的核心图解:
我现在有如下数组: int []arr ={4,6,9,1,11,5,14,6};
我们依旧和冒泡排序一样需要两个指针 这次就是 i 和 j
重点在于:每次随着i的扩大,i走过的路径都是有序的
我们发现0到2,也就是前三个都是有序的!
于是等到i的值为3的时候
注意观测j和i的位置!!!
1是小于9的,所以触发交换
此时发现1还是比前一个 6小 ,所以必须贯彻 每次随着i的扩大,i走过的路径都是有序的
1是小于6的,所以触发交换
接着 是1和4的交换
自此i走过的路程都是有序的了
此后就是不断重复这个过程,直到i走到数组的末尾!
整个数组也有序了!
Java代码
//插入排序
static void insertSort(int []arr){
for (int i = 1; i < arr.length; i++) {
for (int j = i-1; j >=0; j--) {
if (arr[j]>arr[j+1]){//判断条件
swap(arr,j,j+1);
}
else {
break;
}
}
}
}
//交换函数
static void swap(int []arr,int x,int y){
int tmp=arr[x];
arr[x]=arr[y];
arr[y] = tmp;
}
不难看出这个的时间复杂度是O(N^2)
(什么你还不会看时空间复杂度?建议你去b站恶补一下...)
希尔排序
不是这个希尔!
希尔排序,也称为缩小增量排序,是一种基于插入排序的排序算法。它通过比较距离较远的元素,将较小的元素交换到前面,从而逐步减小数组的无序程度,最终实现数组的排序。
她的精髓就在于---分组! 在插入排序的基础上进行分组
一般选择是 将数组分成arr.length/2 然后再把分组范围扩大
比如
第一次这个数组 选择分4组 ,下一次就分成2组
分组后进行选择排序,在数据量小的情况下和插入排序差不多,但是数据量的时候比插入排序快很多
为什么快很多?我也不知道,数学家算出来的,就是快很多
希尔排序的时间复杂度和增量序列的选择有关系,一般情况下希尔排序的时间复杂度为O(n^2) ~ O(n^1.5)。空间复杂度为O(1),是一种原地排序算法。
希尔排序详细图解:
第一次分组,同一个组别的进行选择排序
第二次分组
分组后,排序后的结果
箭头指向的是交换了的位置
我们发现每次组员都会扩大2倍,这个数组到第3次就变成了进行一次选择排序了
所有的希尔排序,到最后都会进行一次完整的选择排序,但是此时数组已经趋近于有序了
再来回顾一下
- 选择一个增量序列,增量序列是一个数组,一般是按照一定的规则(这里是2)生成的;
- 对于每个增量,将数组分为若干个子序列,子序列中的元素相隔增量个位置;
- 对每个子序列进行插入排序,即将每个子序列看成一个独立的数组进行插入排序;
- 增量为1时,进行一次插入排序,排序结束。
Java代码
//交换函数
static void swap(int []arr,int x,int y){
int tmp=arr[x];
arr[x]=arr[y];
arr[y] = tmp;
}
//希尔排序
static void shellSort(int []arr){
for (int k= arr.length/2;k > 0; k/=2){//要不要取等号?不用
for (int i = k; i < arr.length ; i++) {//i和j的范围取值和插入排序一致
for (int j = i-k; j >=0 ; j-=k) {
if (arr[j]>arr[j+k]){
swap(arr,j,j+k);
}
else {
break;
}
}
}
}
哈,谢谢各位同志的阅读,然后呢如果觉得本文对您有所帮助的话,还给个免费的赞捏
Thanks♪(・ω・)ノ