排序总结——插入排序、希尔排序

本文深入讲解了三种排序算法:直接插入排序、折半插入排序和希尔排序。详细介绍了每种算法的基本思想、步骤、代码实现及性能分析,包括稳定性、时间复杂度和空间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

直接插入排序:

基本思想:基本操作是将无需数组的每个元素依次插入有序数组中,这个过程会使有序数组不断增大,无序数组不断减小,最终全部有序,这是原来数组排序完成
步骤:首先拿出为无序数组的元素,将其和有序数组的元素依次进行比较,将符合条件的有序数组的元素移动,最后找到该元素的插入位置,将此元素插入
代码实现

public static void insertSort(int[] arr){
        if(arr == null || arr.length <= 1 ){
            return ;
        }
        for (int i = 1;i < arr.length;i++){
            int temp = arr[i];//拿出要插入的元素
            int j = 0;
            //依次与有序数组进行比较,符合条件的元素后移
            for (j = i-1;(j>=0)&&(arr[j] > temp);j--){
                arr[j+1] = arr[j];
            }
            //找到插入位置,插入元素
            arr[j+1] = temp;
        }
    }

分析:
稳定性:在插入排序中,若插入元素与有序序列的某一元素相等时,不对相等元素进行搬移,而是将欲插入元素插在相等元素的后面,所以是稳定的
时间复杂度:若是完全有序(从小到大)的数组进行插入排序,不会进入元素的搬移这层循环,则时间复杂度为:O(n);若是无序或为逆序数组,都会对有序数组进行遍历,则此时时间复杂度:O(n^2)
空间复杂度:没有开辟新的空间,空间复杂度:O(1)

折半插入排序:直接插入的优化

思想:根据直接插入排序进行优化得来的,优化的地方是,因为前面的序列已经有序,在寻找插入位置时,可用二分查找法进行查找。
**步骤:**拿出待插入的元素,维护有序区间的变量left、righgt以及mid,left为有序区间开始,right为有序区间的结束,若需要插入元素的位置为i,则right=i-1;每次让有序区间的中间位置的元素与待插入元素进行比较,按照排序条件,定位插入区间,直到left<=right时找到插入位置
代码实现:

public static void iInsertSort(int[] arr){
        if(arr == null || arr.length <= 1 ){
            return ;
        }
        for (int i = 1;i < arr.length;i++){
            int temp = arr[i];
            int j = i-1;
            int left = 0;
            int right = i-1;
            //直到有序区间没有元素时停止
            while (left <= right){
                int mid = left + ((right-left)>>1);
                if (arr[mid] < temp){
                    left = mid+1;//若待插入元素比中间位置元素大则将区间定位在mid+1到right
                }else {
                    right = mid-1;//若待插入元素比中间位置元素小则将区间定位在left到mid+1
                }
            }
            for (;j>= right +1;j--){
                arr[j+1] = arr[j];
            }
            arr[j+1] = temp;
        }
    }

分析:
稳定性:稳定
时间复杂度:虽然在查找上效率提高了,但总体来说还是O(n^2)
空间复杂度:O(1)

希尔排序:

思想:排序的思想是将数据分为若干组进行排序,本质是将同组的数据进行插入排序,当分组的间距为1时,此时序列已经接近有序,这时再进行插入排序,序列就完全有序了。
步骤:先设定一个较大的间隔将序列分为若干组,每组数据进行插入排序,再将间隔减小进一步,直到步数为1时是最后一次插入排序,这次插入排序完成后序列完全有序
代码实现:

public static void shell(int[] arr) {
        if(arr == null || arr.length <= 1 ){
            return ;
        }
        int step = arr.length >> 1;
        while (step >= 1) {
            for (int i = step; i < arr.length; i++) {
                int temp = arr[i];//拿出和数组的第一个数组合的数;i=step
                int j = 0;
                //j=i-step  是为了找到与待插入元素组合的数
                for (j = i - step; (j >= 0) && (arr[j] > temp); j -= step) {
                    arr[j + step] = arr[j];//满足条件插入
                }
                arr[j+step] = temp;//j+step的原因是for循环中j又减了一次step
            }
            step >>= 1;//让step每次都缩小2倍
        }
    }

分析:
稳定性:不稳定,一组序列在进行一次插入排序后时稳定的,但是多次之后,相同元素相对位置可能会发生改变,所以不稳定
时间复杂度:nO(logn)-O(n^2)
空间复杂度:O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值