数据结构-经典排序之插入排序与希尔排序

文章目录

插入排序

插入排序(Insertion Sort)是一种简单直观的排序算法,它的工作原理类似于我们手动排序一手扑克牌。算法的基本思想是将一个数据元素从其输入数组中取出,然后将其插入到已排序的数组中适当的位置,以达到排序的目的。
算法步骤
开始假设:
在开始时,我们假设数组的第一个元素是已排序的。这是我们的初始已排序部分。
选择未排序的元素:
从未排序的部分选择一个元素。在第一次迭代中,这个元素是数组的第二个元素。
找到插入位置:
将这个选定的元素与已排序部分的元素逐一比较,从后往前,找到它应该插入的位置。这类似于我们在扑克牌中找到一张牌应该插入的位置。
移动元素:
一旦找到了插入位置,就将该位置及其后面的所有元素向后移动一位,为新元素腾出空间。
插入元素:
将选定的元素插入到腾出的空间中。
重复过程:
重复步骤2到5,直到整个数组排序完成。
示例
假设我们有一个数组 [4, 3, 2, 10, 12, 1, 5, 6],我们按照插入排序的步骤对其进行排序:

开始时,假设第一个元素 [4] 是已排序的。
选择下一个元素 3,与已排序部分的元素 4 进行比较。因为 3 小于 4,所以 3 应该插入到 4 的前面。移动 4 并插入 3,得到 [3, 4]。
选择下一个元素 2,与已排序部分的元素 [3, 4] 进行比较。2 应该插入到最前面,移动其他元素并插入 2,得到 [2, 3, 4]。
以此类推,直到整个数组排序完成。
性能分析
时间复杂度:插入排序的时间复杂度在最坏情况下(即数组是逆序)是 O(n^2),其中 n 是数组的长度。这是因为对于每个元素,我们可能需要将它与已排序部分的所有元素进行比较,并移动它们。然而,在最好情况下(即数组已经排序或接近有序),插入排序的时间复杂度可以降低到 O(n)。
空间复杂度:插入排序的空间复杂度是 O(1),因为它只需要一个额外的空间来存储当前正在插入的元素。
尽管插入排序在处理大规模数据时可能不是最高效的算法,但由于其实现简单且对于小规模或部分有序的数据集表现良好,因此在某些情况下仍然是一个实用的选择。
以下这个插入排序的版本是从后往前进行比较和插入的。对于数组中的每一个元素,它都会找到该元素在已排序部分中的正确位置,并将其插入。

//// 定义InsertSort函数,参数为一个整数数组a和数组的长度n  
void InsertSort(int* a, int n) {
   
     //n为数组数据个数
    // 外层循环:遍历数组中的每一个元素(除了最后一个)  
    for (int i = 0; i < n - 1; i++) {
   
     
        // 初始化end为当前遍历到的元素的索引  
        int end = i;  
        // tmp保存end+1位置(即这一次要插入排序的元素)的值  
        int tmp = a[end + 1];  
          
        // 内层循环:找到tmp应该插入的位置  
        while (end >= 0) {
   
     
            // 如果tmp小于当前end位置的元素,则将end位置的元素后移  
            if (tmp < a[end]) {
   
     
                a[end + 1] = a[end];  
                end--; // 继续向前查找插入位置  
            }  
            else {
   
     
                break; // 如果tmp不小于当前元素,则跳出循环  
            }  
        }  
        // 将tmp插入到正确的位置  
        a[end + 1] = tmp;  //这一句可以放到while循环外,也可以放到while循环内的最后一句,
        //因为每次比较大小都是用目标元素tmp
        //的值(也就是需要进行插入排序的元素)去与它后面的一个元素(也就是a[end])比较,
        //由于tmp已保存了目标元素的值,所以目标元素在进行插入排序时并不需要移动位置。
        //当要插入的目标元素找到了正确的位置(也就是在end+1这个位置)后,才需要
        //移动该元素的位置,通过a[end + 1] = tmp;移动到end+1这个位置。
    }  
}

使用示例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值