经典排序算法1:插入排序

本文讲述几大经典排序算法之一–插入排序的基本原理,详细步骤,C++完整代码实现,复杂度分析。

1. 插入排序基本原理:

将一个序列分为两部分: 已排好序的和未排序的。将为排好序的序列里的元素一次插入已排序序列的合适位置,直到未排序序列为空。
向已排序的序列中插入元素 newEle 的步骤简述如下
从右到左将已排好序的序列中的元素与待插元素比较,将已排好序的序列中大于newEle的元素依次往后移动一个位置,直到遇到不大于newEle的元素,即找到了合适的位置,最后插入待排元素。

1.1. 伪代码: (参照算法导论)

这里写图片描述

1.2. 举例子一步一步描述:

初始序列 A : A[8] = {6 8 5 9 4 3 7}
这里写图片描述

2. C++代码:

#include <iostream>
#include <vector>

using namespace std;
typedef vector<int>::size_type sizeType;
void insertSort(vector<int> &vec)
{
    int vecSize = vec.size();
    int j;
    for (int i = 1; i < vecSize; i++) // i 表示已经排好序的子数组大小减一
    {
        int insertValue = vec[i]; // 将这个值插入已经排好序的数组
        for (j = i - 1; j >= 0; j--)
        {

            if (insertValue >= vec[j])
                break; // 找到了要插入 insertValue 的位置 j
            vec[j + 1] = vec[j];
        }
        vec[j + 1] = insertValue;
    }
}
void init(vector<int> & vec)
{
    int eleValue;
    cout << "input the element values: " << endl;
    while (cin >> eleValue)
    {
        vec.push_back(eleValue);
    }
    cin.clear();
}
void print(vector<int>& vec)
{
    for (sizeType index = 0; index < vec.size(); index++)
    {
        cout << vec[index] << " ";
    }
    cout << endl;
}
int main()
{
    vector<int> vec;
    init(vec);
    cout << "Before sorted : " << endl;
    print(vec);
    insertSort(vec);
    cout << "After Sorted :" << endl;
    print(vec);
    return 0;
}

简单例子测试:
这里写图片描述
复杂用力测试,并计算排序操作时间

        start = clock();
        insertSort(origArr1);
        finish = clock();
        duration = (double)(finish - start) / CLOCKS_PER_SEC;
        cout << "随机生成的序列用时:" << duration << "sec" << endl;

分别输入长度都为 256 的三种已排程度不同的序列,其中
序列1: 随机产生一定大小范围内的数据
序列2: 前100个数已经排好序,后 156个数随机产生
序列3: 完全逆序,即 从大到小依次排列的一组数
运行时间如下
这里写图片描述

3. 算法复杂度分析

根据插入排序的原理可知,消耗运行时间主要由执行的操作步数(这里包括比较元素大小,转移已排序列中的元素,插入新元素)决定,操作步数独立于机器。
case1: 最坏情况,即初始序列已逆序排序。
case2: 最好情况,即初始序列已顺序排序。
根据伪代码求每个操作的执行次数:
case1:
step1: n
step2: n-1
step3: n-1
step4: 1 + 2 + ··· + (n-1) = n ( n-1 )/2*
step5: 1 + 2 + ··· + (n-1) = n(n-1 )/2*
step6: 1 + 2 + ··· + (n-1) = n(n-1 )/2*
step7: n-1
忽略 n 的低次项,最坏情况的时间复杂度是为n 的二次函数,表示为 O(n^2)

case2:
step1: n
step2: n-1
step3: n-1
step4: 1
step5: 0
step6: 0
step7: n-1
即每次将待插入元素比较都有 A[index] <= A[index - 1],即不用移动已排好的序列元素,直接将待插入的元素放到原先的位置即可。操作次数与元素个数 n 成线性关系,即时间复杂度为 O(n)

总体分析:插入排序比较适合已经有部分元素排好序,这样可以减少元素移动的次数。
另外,插入排序一下几个优点
1. 需要增加一个额外的空间存储等待插入的一个元素(newEle),除此之外序列的其他元素都在原有的存储空间内移动,不需要再增加其他额外的空间。
2. 如果有两个元素数值相等,即在比较时 newEle <= A[j], 不会移动 A[j]。 因此,经过排序后,保持了它们的相对位置。即插入排序是稳定的排序方法。

本菜鸟处于初步学习算法阶段,将所学的知识进行总结整理,希望广大网友不吝赐教,提出宝贵的意见,共同探讨,小的将不甚感激。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值