插入排序和希尔排序

目录

插入排序

插入排序代码实现:

插入排序思路:

希尔排序:

什么是希尔排序:

希尔排序代码实现:

希尔排序思路:


插入排序(稳定)

假设有这样一个数组,想要从小到大进行排序:

复制代码
int[] array = {4,9,5,8,6,2,10,7,3,1};

插入排序代码实现:

复制代码
public static void insertSort(int[] arr) {
        for (int i = 1; i < arr.length; i++) {
            int ret = arr[i];
            int j = i - 1;
            for (; j >= 0 ; j--) {
                if(arr[j] > ret) {
                    arr[j+1] = arr[j];
                }else {
                    //arr[j+1] = ret;
                    break;
                }
            }
            arr[j+1] = ret;
        }
    }

代码运行结果:

可以看到,结果是从小到大排序的。

插入排序思路:

假设有个待排序数组(黑色数字),定义一个 i 下标,一个 j 下标,再定义一个记录i下标的值的ret。

首先,i 下标从 1 位置开始,j 下标在 i - 1位置开始,当 j 下标的值比 ret 的值大,把 j 下标的值给到 j+1 的位置。反之 把ret 的值给到 j+1的位置。以此往复。

值得注意的是,比如数组的最小的元素(上图的是0), j 会到达下标为 -1 的位置,此时,循环里的 arr[j+1] = ret; 这句代码就执行不到了,意思就是数组最小元素 0 放不到下标为 0 的位置。所以在外面 加上一句 arr[j+1] = ret; 代码。这句代码和 循环里的这句代码重复了,就把 循环里的这句代码注释了。

希尔排序(不稳定):

什么是希尔排序:

把待排序数据分成多个组,所有距离为的记录分在同⼀组内,并对每⼀组内的记录进行插入排序。然后,重复上述分组和排序的过程。当到达=1时,所有记录在统⼀组内排好序。

什么意思呢?

如图:

先假定 gap的大小,这里初始的 gap 是5,让 每个数据之间都相差 距离为 gap 的大小,如果后面的最远的数据相差比 gap小就 不相连,这样就为一组了。下一个 组 从第二个数据开始,直到包含所有数据。分组就结束了。

然后,对其中的一趟的 每一组进行插入排序,再不断缩小gap的大小,直到gap的大小为1,gap的大小为1就是一次完整的插入排序了。当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。

所有,可以说希尔排序是对插入排序的优化。

一样,我们假设有这样一个数组,想要从小到大进行排序:

复制代码
 int[] array = {4,9,5,8,6,2,10,7,3,1};

希尔排序代码实现:

复制代码
 public static void shellSort(int[] arr) {
        int gap = arr.length / 2;
        while(gap > 0) {
            shell(arr,gap);
            gap /= 2;
        }
    }

    public static void shell(int[] arr,int gap) {
        for (int i = gap; i < arr.length; i++) {
            int ret = arr[i];
            int j = i - gap;
            for (; j >= 0 ; j -= gap) {
                if(arr[j] > ret) {
                    arr[j+gap] = arr[j];
                }else {
                    //arr[j+1] = ret;
                    break;
                }
            }
            arr[j+gap] = ret;
        }
    }

希尔排序思路:

结合上图,这是gap 为 2 的时候的情况,与插入排序类似,结合代码看,把红色组别看成一组数据,先让 下标 i 等于 gap的位置,j 在 i - gap 的位置,确保他们是在红色组别位置进行插入排序,下一次,i 加加,到了绿色组别位置,再让 j 在 i - gap 的位置,确保他们是在绿色组别位置进行插入排序。可以看出,他们是在红色和绿色组别交替进行插入排序的。

直到 gap 为 1 ,就可以看作一次普通的插入排序了。

至于起始的 gap 选多大是无法给出正确答案的,希尔排序时间复杂度不好计算,因为 gap 的取值很多,导致很难去计算。

相关推荐
地平线开发者9 分钟前
C++ 部署的性能优化方法
c++·算法·自动驾驶
怀念无所不能的你11 分钟前
acwing背包问题求方案数
学习·算法·动态规划·dp
晚上不睡觉的周某人12 分钟前
Java应用7(类集)
java·开发语言·windows
码银16 分钟前
Java Stream流
java·开发语言
尽兴-18 分钟前
TCP vs UDP:核心区别、握手过程与应用场景(附对比图)
java·网络协议·tcp/ip·udp
Yingye Zhu(HPXXZYY)30 分钟前
洛谷P12238 [蓝桥杯 2023 国 Java A] 单词分类
c++·算法·蓝桥杯
lqlj223332 分钟前
如何在idea中写spark程序
java·spark·intellij-idea
Kiri霧41 分钟前
Java 多线程基础:Thread 类详解
java·开发语言
Phoebe鑫1 小时前
数据结构每日一题day13(链表)★★★★★
数据结构·链表
冼紫菜1 小时前
探索微服务入口:Spring Cloud Gateway 实战指南
java·开发语言·后端·spring cloud·微服务·gateway