插入排序和希尔排序

目录

插入排序

插入排序代码实现:

插入排序思路:

希尔排序:

什么是希尔排序:

希尔排序代码实现:

希尔排序思路:


插入排序(稳定)

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

复制代码
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 的取值很多,导致很难去计算。

相关推荐
~无忧花开~几秒前
CSS学习笔记(五):CSS媒体查询入门指南
开发语言·前端·css·学习·媒体
kesteler2 分钟前
R-切割数据
开发语言·r语言
哞哞不熬夜9 分钟前
JavaEE--SpringIoC
java·开发语言·spring boot·spring·java-ee·maven
滑水滑成滑头10 分钟前
**点云处理:发散创新,探索前沿技术**随着科技的飞速发展,点云处理技术在计算机视觉、自动驾驶、虚拟现实等领域的应用愈发广
java·python·科技·计算机视觉·自动驾驶
newxtc13 分钟前
【猿辅导-注册安全分析报告-无验证方式导致安全隐患】
开发语言·selenium·安全·yolo·安全爆破
张人玉15 分钟前
c#WPF基础知识
开发语言·c#·wpf
千里马-horse19 分钟前
fastddsgen.jar 简介
java·jar·fast dds·fastddsgen
TT哇19 分钟前
【Maven】Maven设置国内源
java·maven
violet-lz33 分钟前
数据结构四大简单排序算法详解:直接插入排序、选择排序、基数排序和冒泡排序
数据结构·算法·排序算法
·白小白38 分钟前
力扣(LeetCode) ——118.杨辉三角(C++)
c++·算法·leetcode