七中常见的排序算法(插入排序,希尔排序,堆排序,选择排序,冒泡排序,选择排序,归并排序)

本文详细介绍了七种常见的排序算法:插入排序、希尔排序、堆排序、选择排序、冒泡排序、快速排序和归并排序,包括它们的原理、性能分析和Java实现。每种算法的特点和适用场景也被提及,如插入排序在数组接近有序时效率较高,而快速排序在平均情况下的时间复杂度为O(nlogn),但最坏情况下为O(n^2)。归并排序是稳定的排序算法,适用于外部排序和链表排序。
摘要由CSDN通过智能技术生成

一.插入排序
让bound指向第一个元素,将所有元素分为[0,bound)已排序区间和[bound,size)待排序区间, 先取bound位置的元素,往前面的已排序区间中插入,插入完毕后已排序区间仍然是有序的,把bound位置的元素在前面找一个合适的位置,同时需要搬运相关元素.
在这里插入图片描述
接下来用Java 来实现这种算法:

 public static void insertSort(int[] array) {
   
        // 通过 bound 来划分出两个区间
        // [0, bound) 已排序区间
        // [bound, size) 待排序区间
        for (int bound = 1; bound < array.length; bound++) {
   
            int v = array[bound];
            int cur = bound - 1;  // 已排序区间的最后一个元素下标
            for (; cur >= 0; cur--) {
   
                // 注意!!!! 这个条件如果写成 >= , 咱的插入排序就不是稳定排序了
                if (array[cur] > v) {
   
                    array[cur + 1] = array[cur];
                } else {
   
                    // 此时说明已经找到了合适的位置
                    break;
                }
            }
            array[cur + 1] = v;
        }
    }

插入排序性能分析:
时间复杂度:0(N^2)
空间复杂度:0(1)
稳定性: 稳定排序
插入排序两个重要特点:
1.当待排序区间元素比较少的时候,排序效率很高.
2.当整个数组比较接近有序的时候,排序效率也很高.

二.希尔排序:
进阶版本的插入排序,先分组,针对每个组进行插入排序,逐渐缩小组的个数,最终整个数组就接近有序了
9 5 2 7 3 6 8 10 7.5 12 6 4
gap=3 相当于把整个数组分成三组.每隔三个元素分为一组
第一组 :9 7 8 12
第二组: 5 3 10 6
第三组:2 6 7.5 4
先分组然后针对每一组进行插入排序.得到结果:
第一组:7 8 9 12
第二组:3 5 6 10
第四组:2 4 6 7.5
整体:
7 3 2 8 5 4 9 6 6 12 10 7.5
现在数组比之前更有序,接下来进行第二趟排序:
gap=2 把整个数组分成两组:
第一组:7 2 5 9 6 10
第二组:3 8 4 6 12 7.5
排序并合并后:
2 3 5 4 6 6 7 7.5 9 8 10 12
让gap=1 ,只剩下一组,此时一定能得到一个完整的有序结果:
2 3 4 5 6 6 7 7.5 8 9 10 12
接下来Java代码实现:

public static void shellSort(int[] array) {
   
        int gap = array.length / 2;
        while (gap > 1) {
   
            // 需要循环进行分组插排
            insertSortGap(array, gap);
            gap = gap / 2;
        }
        insertSortGap(array, 1);
    }

    private static void insertSortGap(int[] array, int gap) {
   
        // 通过 bound 来划分出两个区间
        // [0, bound) 已排序区间
        // [bound, size) 待排序区间

        // 当吧 gap 替换成 1 的时候, 理论上这个代码就和前面的插排代码一模一样.
        for (int bound = gap; bound < array.length; bound++) {
   
            int v = array[bound];
            int cur = bound - gap;  // 这个操作是在找同组中的上一个元素
            for (; cur >= 0; cur -= gap) {
   
                if (array[cur] > v) {
   
                    array[cur + gap] = array[cur];
                } else {
   
                    // 此时说明已经找到了合适的位置
                    break;
                }
            }
            array[cur + gap] = v;
        }
    }

希尔排序性能分析:
时间复杂度:理论极限是0(N^1.3),如果按照 size/2,size/4,…1.
空间复杂度:0(1)
稳定性:不稳定 (分组的时候可能把相同的值分到不同组中,也就无法保证相对顺序.

三.选择排序
基于打擂台的思想,每次从数组中找出最小值,然后把最小值放到合适的位置上;
下面给定一组元素:
9 5 2 7 3 6 8
让bound=0,[0,bound)是已排序区间,[bound,size)是待排序区间
按照打擂台的方式从待排序区间中找到一个最小值放到bound位置上与擂主交换.
第一趟排序后:
2 9 5 7 3 6 8
第二趟排序后:
2 3 9 7 5 6 8

代码实现:

 public static void selectSort(int[] array) {
   
        for (int bound = 0; bound < array.length; bound++) {
   
            // 以 bound 位置的元素作为擂主. 循环从待排序区间中取出元素和擂主进行比较
            // 如果打擂成功, 就和擂主交换.
            for (int cur = bound + 1; cur < array.length; cur++
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值