zoukankan      html  css  js  c++  java
  • 绝知此事要躬行之——插入排序

    插入排序可以说是十分简单的排序算法了,但是完整的完成对该算法的测试,并不是一件容易的事情。其中还有很多其他的知识点需要我们学习:

    在本次测试中,采用了两种方法,控制板输入和随机数产生的方法。从中也学到了很多知识

    无代码言吊,上代码:

     1 # include"iostream"
     2 # include "vector"
     3 # include "ctime"
     4 # include "cstdlib"  // 如果我们想通过随机数来验证我们的想法。应该预先给vecot分配内存
     5 using namespace std;
     6 void insert_sort(vector<int> & );
     7 int main()
     8 {
     9     const int MAX_NUMBER = 5000;//生成的最大的随机数
    10     const int MIN_VALUE = 1;
    11     const int MAX_VALUE = 40000;
    12     vector<int> a;
    13     a.reserve(MAX_NUMBER);//预先分配内存你,预防迭代器的失效。否则内存搬移,迭代器容易失效
    14 
    15     // 采用控制台输入的方式 
    16     //int temp;
    17     //while (cin >> temp)
    18     //{
    19     //    a.push_back(temp);
    20     //    if (cin.get() == '
    ') //注意这种用法,用的很多。
    21     //    {
    22     //        break;
    23     //    }
    24     //}
    25 
    26     //采用随机数生成法。
    27     srand((unsigned)time(NULL));//根据时钟生成不同的种子,保证每次运行程序产生不同的随机数
    28     for (int i = 1; i <= MAX_NUMBER; i++)
    29     {
    30         int temp;
    31         temp = (rand() % (MAX_VALUE - MIN_VALUE + 1)) + MIN_VALUE;//生成[MIN_VALUE,MAX_VALUE]之间的整数随机数
    32         a.push_back(temp);
    33     }
    34     //cout << "The initial order: ";    数据量太大,不适合输出
    35     //vector<int>::iterator ia = a.begin();
    36     //for (; ia != a.end(); ia++)
    37     //{
    38     //    cout << *ia << " ";
    39     //}
    40     //cout << endl;
    41     clock_t start, finish;
    42     double runtime;
    43     start = clock();
    44     insert_sort(a);
    45     finish = clock();
    46     runtime = (double)(finish - start) / CLOCKS_PER_SEC;
    47     cout << "The time of Insert Sort algorithm is:" << runtime << "s" << endl;
    48     cout << "The new initial order: ";
    49     //for (ia = a.begin(); ia != a.end(); ia++)
    50     //{
    51     //     cout << *ia << " ";
    52     //}
    53     //cout << endl;
    54     system("pause");
    55     return 0;
    56 }
    57 
    58 void insert_sort( vector<int> & sort_a)  ///注意,采用vector<int> 是可以作为参数进行传递的,那么是否可以作为返回类型使用呢?
    59 {
    60     int a_size ,temp;
    61     a_size = sort_a.size();
    62     for (int i = 1,j; i < a_size; i++)//注意,将j放在这里声明,不要放在下一个循环中声明,否则会造成多次声明?(但是作用域没变,多次声明应该被禁止,所以没有多次声明?)
    63     {
    64         temp = sort_a[i];
    65         for (j = i; (j > 0) && (sort_a[j - 1] > temp); j--)//这里先后顺序的差别,导致了数组的越界,
    66         {   
    67             sort_a[j] = sort_a[j-1];
    68         }
    69         sort_a[j] = temp;
    70         
    71     }
    72 }

    对于插入排序算法,其实本身而言并没有什么好说的,算法很简单,总结起来就是三步:

           1  从第二个数开始遍历(直到最后一个数),将当前数缓存(temp);

           2  对于每一个当前值,比较其前面的所有数和该当前值的大小,如果比当前值大,将这个数向后移动一次(注意,并不会出现数据覆盖丢失数据的情况,思考为什么?)

           3 将temp中的数插入到2执行结束后,索引所在的序列号

    (如果说的不太清楚,看代码58-72)

    图中注释掉的代码为控制台输入的情况:

    对于控制台输入的方式,注意:17-23行所在代码,这其中的代码是:未知输入整数的个数,以输入回车键作为结束标志符,其实这很符合人的控制台输入习惯。但 如果我们没有if (cin.get() == ' ')这句判断,无论我们怎么按回车键都不会结束输入,这是为什么呢?因为 cin 的输入对于文件系统是EOF结束,但是对于控制台输入,没有这个东西啊!!!其实有,就是快捷键Ctrl+z,!!!也就是,但我们想结束输出时,按Ctrl+z,再按回车键,就结束了我们的输入!!what a fuck!,麻蛋,这不是智障设计吗?谁输入完了,会按Ctrl+z,这种反人类设计真的蠢到了极点。于是,我们只能采用cin.get()读取字符,判断遇到的回车" ",就结束。这一点,我觉得是c++的iostream设计的很失败的地方(其实包括string),给人一种既不想丢弃c语言的操作,又要引入c++的新特性一样,累赘复杂。马丹,希望有一天能改进吧。

    值得关注的一点是 vector<int> &作为插入排序的形参类型(实际上也可以作为返回类型),我本身并不知道可以这么做,只是觉得可以这么做(因为不想采用c语言中的数组或者指针这种方式,想纯粹的采用c++的特性编程),结果发现可以,编译器没有报错。这一点凸显了c++的强大之处。

    关于随机数的说明:

    控制台输入可以验证算法的正确性,但没法体现算法的效率,我们采用随机数生成的办法就是为了验证算法的执行效率。

    关于随机数的声明,需要头文件# include "cstdlib" ,当然采用rand()函数就可以了。问题在于,生成指定范围的随机数,第31行的代码告诉了我们应该怎么做。且,rand()有个特点,每次运行程序,生成的随机数是相同的(我们下次运行程序时,随机数不会变,但我们当然希望随机数可以变,于是就需要一个时间种子,27行的srand()就可以使得随机数随着时间变化变化。当然,我们需要知道算法的执行效率,就需要知道执行时间复杂度。于是需要借用系统时间统计函数clock(),这就又需要头文件ctime了

    关于插入排序的执行效率,我们可以根据不同的数据规模,来看看其运行时间

    插入算法效率
    数据个数 时间/s
    5000 0.830
    10000 3.325
    20000 13.207
    30000 29.878

    (PS)你可以执行上述代码,修改MAX_NUMBER ,可以看看执行的时间。

    从执行结果看,随着数据个数的增加,执行时间的增加很明显,很明显,其变化趋势超过了线性规律,即时间时间复杂度超过了O(n),实际上,插入排序算法的时间复杂度为O(n2),可见插入排序其实并不是一种高效的算法

  • 相关阅读:
    request实现登录
    python之对象
    python基础之迭代与解析
    python基础之函数
    linux expect命令使用入门
    Python socket
    1
    蓝牙
    SQL查询语句
    iOS常用小知识纪录
  • 原文地址:https://www.cnblogs.com/shaonianpi/p/10802722.html
Copyright © 2011-2022 走看看