C++抽象编程——算法分析(8)——插入排序算法与分析
来源:互联网 发布:烟台plc编程 编辑:程序博客网 时间:2024/06/07 20:37
本来算法分析系列算是写完了(其中我忽略了数学归纳法那一部分内容,因为我觉得我们高中学过就没必要再提一次)。但是教材强调我们要重点看看练习题的第二题。我也看了一下,确实很不错。这道题讨论的是插入排序(insertion sort)算法。题目如下:
练习2——插入排序(insertion sort)
还有其他几种排序算法表现出选择排序的O(N^2)行为。 其中最重要的是插入排序,其操作如下。你可以依次选择vector0中的每个元素,与选择排序算法一样。但是,在该过程的每个步骤中,目标不是找到最小的剩余值并将其切换到正确的位置,而是确保到目前为止所考虑的值是相对于彼此正确排序的。虽然这些值可能会随着更多元素的处理而改变,但它们在自身中形成有序的序列。
例如,如果你再次考虑我们之前排序示例中使用的数据,则插入排序算法的第一个循环不需要工作,因为一个元素的向量总是被排序:
在下一个循环中,你需要将25放在正确的位置,这意味着您需要交换56和25以达到以下配置:
在第三个循环,你需要找到值37应该去哪里。为了做到这一点,你需要向前遍历早期的元素,你知道这些元素是已经排好序的。当你走的时候,你需要把每一个较大的元素一个位置向右移动,这最终为你要插入的价值腾出空间。 在这种情况下,56被向后移动了一个位置,37个在第1位上升。因此,第三个循环后的配置如下所示:
在每个循环之后,vector的初始部分总是被排序,这意味着以这种方式循环遍历所有位置将对整个vector进行排序。
插入排序算法在实践中很重要,因为如果向量已经以正确的顺序或者已经或多或少地排好序,则它在线性时间运行(因为此时只是相当于遍历)。因此,我们通常使用插入排序将只有少数元素并未被排序的的大型vector中。这样耗时是最少的。
目的:编写一个程序实现插入排序算法(用sort作为函数原型)。 构造一个非正式的参数来表明插入排序的最坏情况是O(N^2)
代码的实现
我刚刚花了20分钟写出了这个简短的代码,实话,惭愧写了那么久。但是我确实学到了新的技巧,现在来分享:
#include <iostream>#include <vector>using namespace std;/*函数原型*/ void sort(vector<int> & vec);/*主函数*/ int main(){ vector<int> vec; for(int i = 0; i < 8; i++){ int n; cin >> n; vec.push_back(n); } sort(vec); for(int k = 0; k < vec.size(); k++){ cout << vec[k] << " "; } return 0;}void sort(vector<int> &vec){ for(int i = 1; i < vec.size(); i++){ int key = vec[i];//记录该位置的值,这个位置之前的数字都已经被排序好 //满足条件之后,往后挪动为插入腾出空间 while(key < vec[i - 1] && i > 0){ vec[i] = vec[i- 1]; i--; vec[i] = key; } }}
运行结果如图:
代码分析与反思
其实写这段代码的时候头脑还是挺清晰的。在vec[i]前面的数一定是排序好的,只要vec[i]前面的数比它小,那么就插入到这个数的前面,然后继续比较前者是不是还比它小。我们重点解析一下这段代码:
while(key < vec[i - 1] && i > 0){ vec[i] = vec[i- 1]; i--; vec[i] = key; }
我们假设这个时候i = 2;那么数据中的37前面的25和56是已经排序好的。我们先将vec[i - 1]的值先赋值给vec[i].这个时候
数据就是:
这就相当于我们完成了后移,为插入腾出空间。此时 i 减去1,再用记录了37的key赋值给vec[i] (此时就是vec[1]),完成插入)。那我们能不能把
vec[i] = key;
放在while循环的后面呢?当然是可以的,前者是边后移边插入,后者是先全部后移,然后插入。
现在我们可以来回答提出的两个问题了,最好的情况是什么呢?当然是已经排好序的时候啦。因为我们的操作是遍历,然后比较大小再进行插入操作的。如果所有的数据都是后一位大于前一位,那么说明的就是while循环根本都不用执行,因此我们所做的也就仅仅是遍历的过程,也就是线性的复杂度O(N),好了 现在我们再讨论一下最坏的情况,是排序一组毫无规则的vector吗?很明显不是的,因为再没有规则它前面都可以有比它小或者大的数,意味着它不用进行所有的插入操作了。最坏的情况我想应该就是让你去用插入排序去将一组降序排列的vector变为升序排序的vector了吧,就像 :
8 7 6 5 4 3 2 1
用插入排序排成:
1 2 3 4 5 6 7 8
每个操作都要移动N-1次。那么我们进行了N次,所以显然跟选择排序的s算法复杂度一样为O(N^2)
C++抽象编程——算法分析(1)——选择排序
- C++抽象编程——算法分析(8)——插入排序算法与分析
- C++抽象编程——算法分析(7)——快速排序算法分析
- 《数据结构与算法分析(c描述)》—— 插入排序&希尔排序
- C++抽象编程——算法分析(4)——合并排序算法
- C++抽象编程——算法分析(6)——快速排序算法
- 算法与分析设计 实验——插入排序C语言实现
- C++抽象编程——算法分析(1)——选择排序
- 排序算法—直接插入排序算法分析与实现(Python)
- 《数据结构与算法分析(c描述》—— 快速排序
- 数据结构与算法分析(Java语言描述)(2)—— 插入排序
- 常用的排序算法性能分析(1)—— 选择排序、插入排序、希尔排序
- 排序算法—冒泡排序算法分析与实现(Python)
- 排序算法—选择排序算法分析与实现(Python)
- 排序算法—希尔排序算法分析与实现(Python)
- 排序算法—堆排序算法分析与实现(Python)
- 排序算法—归并排序算法分析与实现(Python)
- 排序算法—快速排序算法分析与实现(Python)
- 算法分析之插入排序——动态数组实现
- Ubuntu gcc/g++ 版本切换
- 后门构建工具Backdoor Factory
- jQuery $.ajax() 之登录
- jdk源码解析--深入探讨Iterator模式
- Java中如何遍历Map对象的4种方法
- C++抽象编程——算法分析(8)——插入排序算法与分析
- 单例模式
- mysql存储过程传入表名做参数,进行分页处理
- 【个人笔记重点,不作为参考】主题:JSX语法与函数式编程
- xgboost特征选择
- 单链表的快速排序
- [SCOI2007]蜥蜴
- 第四单元练习题
- 关于SVN的一些概念和配置文件理解