首页 > 编程语言 >常见的排序算法——插入排序(二)

常见的排序算法——插入排序(二)

时间:2024-04-08 11:24:49浏览次数:17  
标签:... 4.0 int 插入排序 元素 算法 time 排序

本文记述了插入排序微小改进的基本思想和一份参考实现代码,并在说明了算法的性能后用实验进行了验证。

◆ 思想

内存中的数据交换是昂贵的操作,此改进实现了不需要交换的插入排序。

将第一个元素之后的所有元素作为待排序范围,将前面的所有元素作为已排序范围。通过一一比较,逐个将已排序范围内比第二个元素大的所有元素右移一位,使第二个元素被插入到了正确的位置。然后将第二个元素之后的所有元素作为新的待排序范围,将前面的所有元素作为已排序范围。重复以上的比较、查找和交换,直至待排序范围中无元素为止。如要得到逆序的结果,则仅需改变比较的方向即可。

◆ 实现

排序代码采用《算法(第4版)》的“排序算法类模板”实现。(代码中涉及的基础类,如 Array,请参考算法文章中涉及的若干基础类的主要API

// insertion2.hxx

...

class Insertion2
{

    ...

    template
    <
        class _T,
        class = typename std::enable_if<std::is_base_of<Comparable<_T>, _T>::value>::type
    >
    static
    void
    sort(Array<_T> & a)
    {
        int N = a.size();
        for (int i = 1; i < N; ++i) {                              // #1
            _T t = a[i];
            int j;
            for (j = i; j > 0 && __less__(t, a[j-1]); --j)       // #2
                a[j] = a[j-1];
            a[j] = t;
        }
    }

    ...

    template
    <
        class _T,
        class = typename std::enable_if<std::is_base_of<Comparable<_T>, _T>::value>::type
    >
    static
    bool
    __less__(_T const& v, _T const& w)
    {
        return v.compare_to(w) < 0;             // #3
    }
    
    ...

反复处理待排序范围(#1),逐个将已排序范围内比待插入元素大的所有元素右移一位,使该元素被插入到了正确的位置(#2)。将 '<' 改为 '>',即得到逆序的结果(#3)。

◆ 性能

时间复杂度 空间复杂度 是否稳定
N^2 1

◆ 验证

测试代码采用《算法(第4版)》倍率实验方案,验证其正确性并获取时间复杂度数据。

// test.cpp
    
...
time_trial(int N)
{
    Array<Double> a(N);
    for (int i = 0; i < N; ++i) a[i] = Std_Random::random();    // #1
    Stopwatch timer;
    Insertion2::sort(a);                     // #2
    double time = timer.elapsed_time();
    assert(Insertion2::is_sorted(a));            // #3
    return time;
}

...
test(char * argv[])
{
    int T = std::stoi(argv[1]);          // #4
    double prev = time_trial(512);
    Std_Out::printf("%10s%10s%7s\n", "N", "Time", "Ratio");
    for (int i = 0, N = 1024; i < T; ++i, N += N) {            // #5
        double time = time_trial(N);
        Std_Out::printf("%10d%10.3f%7.1f\n", N, time, time/prev);   // #6
        prev = time;
    }
}
...

用 [0,1) 之间的实数初始化待排序数组(#1),打开计时器后执行排序(#2),确保得到正确的排序结果(#3)。整个测试过程要执行 T 次排序(#4)。每次执行排序的数据规模都会翻倍(#5),并以上一次排序的时间为基础计算倍率(#6),

此测试在实验环境一中完成,

$ g++ -std=c++11 test.cpp std_out.cpp std_random.cpp stopwatch.cpp type_wrappers.cpp

$ ./a.out 8

     N      Time  Ratio
  1024     0.115    4.1
  2048     0.457    4.0
  4096     1.813    4.0
  8192     7.223    4.0
 16384    28.987    4.0
 32768   116.038    4.0
 65536   463.018    4.0
131072  1868.986    4.0 

可以看出,随着数据规模的成倍增长,排序所花费的时间将是上一次规模的 4 倍。将数据反映到以 2 为底数的对数坐标系中,可以得到如下图像,

test_data

O(N^2) 代表了平方级别复杂度下的理论排序时间,该行中的数据是以 Time 行的第一个数据为基数逐一乘 4 后得到的结果(因为做的是倍率实验,所以乘 (2)^2 即 4)。

◆ 最后

完整的代码请参考 [gitee] cnblogs/18120503

写作过程中,笔者参考了 《算法(第4版)》 一书中的插入排序、实验题 2.1.25、“排序算法类模板”和倍率实验。致作者 Sedgwick,Wayne 及译者谢路云。

标签:...,4.0,int,插入排序,元素,算法,time,排序
From: https://www.cnblogs.com/green-cnblogs/p/18120503

相关文章

  • 自适应鱼群算法改进随机森林的变压器故障诊断(IFSA-RF模型)(Matlab代码实现)
    ......
  • 自适应鱼群算法改进随机森林的变压器故障诊断(IFSA-RF模型)(Matlab代码实现)
    ......
  • 蓝桥杯-算法赛第9场强者:贝贝的2.0
    题意:n个节点的有根树,问孩子节点最少是多少,可以满足任意两条长度为k的链有公共节点。思路:一开始想的是以根为中间点,然后构造边。但是发现样例过不了,样例说的很清楚,根节点也作为一个叶子节点去构造,然后把叶子节点作为中间点(这样可以省去一个叶子节点的计数)。最后就是如何处理的问题......
  • 敏感词检测-DFA算法笔记及实现
    引子敏感词检测,这个是很多文字类服务都要遇到的问题,最近项目上接触到,特此调研梳理下这部分的内容。比如当我们输入一些包含暴力或者色情的文本,系统会阻止信息提交。敏感词过滤就是检查用户输入的内容有没有敏感词。OK,让我们开始吧。一、算法原理简介一般敏感词检测之后......
  • 二叉排序树(BST)
    定义二叉排序树是一种特殊的二叉树,其中左子树中的所有节点都小于根节点,右子树中的所有节点都大于根节点(如下图所示)。因此构造过程需要确保插入的元素能够按照这个规则被正确地插入到树中性质1、如果初始状态是一个空树,则插入每个元素的时间复杂度是O(logn),其中n是树中节......
  • 三种算法实例(二分查找算法、插入排序算法、贪心算法)
    当我们听到“算法”这个词时,很自然地会想到数学。然而实际上,许多算法并不涉及复杂数学,而是更多地依赖基本逻辑,这些逻辑在我们的日常生活中处处可见。在正式探讨算法之前,有一个有趣的事实值得分享:你已经在不知不觉中学会了许多算法,并习惯将它们应用到日常生活中了。下面我将举......
  • 蓝桥杯练习系统(算法训练)ALGO-963 转圈游戏
    资源限制内存限制:128.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s问题描述n个小伙伴(编号从0到n-1)围坐一圈玩游戏。按照顺时针方向给n个位置编号,从0到n-1。最初,第0号小伙伴在第0号位置,第1号小伙伴在第1号位置,……,依此类推。游戏规......
  • 蓝桥杯练习系统(算法训练)ALGO-962 积木大赛
    资源限制内存限制:128.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s问题描述THU幼儿园举办了一年一度的“积木大赛”。今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1的积木组成,第i块积木的最终高度需要是hi。在搭建开始......
  • 有趣的算法
    青蛙跳台问题现在一共有n个台阶,一只青蛙每次只能跳一阶或是两阶,那么一共有多少种跳到顶端的方案?例如n=2,那么一共有两种方案,一次性跳两阶或是每次跳一阶。现在请你设计一个Java程序,计算当台阶数为n的情况下,能够有多少种方案到达顶端。解决方法假设青蛙已经站在了顶端(n),那么......
  • 基于项目的协同过滤推荐算法(Item-Based Collaborative Filtering Recommendation Alg
    前言协同过滤推荐系统,包括基于用户的、基于项目的息肉通过率等,今天我们读一篇基于项目的协同过滤算法的论文。今天读的论文为一篇名叫《基于项目的协同过滤推荐算法》(Item-BasedCollaborativeFilteringRecommendationAlgorithms)。摘要Recommendersystemsapplyknowledg......