经典算法之三:插入排序及二分优化
来源:互联网 发布:linux激活虚拟网卡 编辑:程序博客网 时间:2024/05/16 12:12
直接插入排序(Insertion Sort)的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,直到全部记录插入完成为止。
设数组为a[0…n-1]。
1. 初始时,a[0]自成1个有序区,无序区为a[1..n-1]。令i=1
2. 将a[i]并入当前的有序区a[0…i-1]中形成a[0…i]的有序区间。
3. i++并重复第二步直到i==n-1。排序完成。
直接插入排序
基本思想
当插入第
直接插入排序图示
从上到下,分别展示了直接排序算法的所有可能的过程,包括相同排序码的排序方式(保持了原来的顺序,说明是稳定排序)以及in-place操作中的元素移动等。
直接插入排序算法分析
设待排序对象个数为
n ,则该算法的主程序执行n−1 趟排序码比较次数和对象移动次数与对象排序码的初始排列有关。
- 最好情况下,排序前对象已经按照要求的有序。比较次数(KCN):
n−1 ; 移动次数(RMN):为0 。则对应的时间复杂度为O(n) 。 - 最坏情况下,排序前对象为要求的顺序的反序。第
i 趟时第i 个对象必须与前面i 个对象都做排序码比较,并且每做1次比较就要做1次数据移动(具体可以从下面给出的代码中看出)。比较次数(KCN):∑n−1i=1i=n(n−1)2≈n22 ; 移动次数(RMN):为∑n−1i=1i=n(n−1)2≈n22 。则对应的时间复杂度为O(n2) 。 - 如果排序记录是随机的,那么根据概率相同的原则,在平均情况下的排序码比较次数和对象移动次数约为
n24 ,因此,直接插入排序的时间复杂度为O(n2) 。
直接插入排序算法的特点
- 它是稳定排序,不改变相同元素原来的顺序。
- 它是in-place排序,只需要
O(1) 的额外内存空间。 - 它是在线排序,可以边接收数据边排序。
- 它跟我们牌扑克牌的方式相似。
- 对小数据集是有效的。
算法分析
直接插入排序的算法性能
时间复杂度
当数据正序时,执行效率最好,每次插入都不用移动前面的元素,时间复杂度为O(N)。
当数据反序时,执行效率最差,每次插入都要前面的元素后移,时间复杂度为O(N2)。
所以,数据越接近正序,直接插入排序的算法性能越好。
空间复杂度
由直接插入排序算法可知,我们在排序过程中,需要一个临时变量存储要插入的值,所以空间复杂度为 1 。
算法稳定性
直接插入排序的过程中,不需要改变相等数值元素的位置,所以它是稳定的算法。
完整参考代码
直接插入排
#include <bits/stdc++.h>using namespace std;const int MAXN=1e5;void Init(int *a,int *b,int n){ srand(time(NULL)); for(int i=0; i<n; i++) b[i]=a[i]=rand()%100;}void P(int *a,int n){ for(int i=0; i<n; i++) cout<<a[i]<<" "; cout<<endl;}void Insert_Sort(int *a,int n){ int i,j; for(i=1; i<n; i++) { if(a[i]<a[i-1]) { int t=a[i]; for(j=i-1; j>=0&&a[j]>t; j--) { a[j+1]=a[j]; } a[j+1]=t; } //P(a,i); }}//二分优化void Insert_Sort_Binary(int *a,int n){ for(int i=1; i<n; i++) { if(a[i]<a[i-1]) { int left=0; int right=i-1; int t=a[i]; while(left<=right) { int mid=(left+right)>>1; if(a[mid]>t) right=mid-1; else left=mid+1; } for(int j=i-1; j>=left; j--) { a[j+1]=a[j]; } a[left]=t; } //P(a,i); }}int main(){ int a[MAXN],b[MAXN]; char ch; do { Init(a,b,MAXN); //P(a,MAXN); time_t t1=clock(); Insert_Sort(a,MAXN); time_t t2=clock(); cout<<t2-t1<<endl; //P(a,MAXN); //P(b,MAXN); time_t t3=clock(); Insert_Sort_Binary(b,MAXN); time_t t4=clock(); cout<<t4-t3<<endl; //P(b,MAXN); } while(ch=getchar()); return 0;}
参考博客:http://blog.csdn.net/morewindows/article/details/6665714
https://www.cnblogs.com/jingmoxukong/p/4303270.html
http://blog.csdn.net/lg1259156776/article/details/48689323
https://www.cnblogs.com/Braveliu/archive/2013/01/09/2852641.html
https://www.cnblogs.com/huangxincheng/archive/2011/11/20/2255695.html
- 经典算法之三:插入排序及二分优化
- 经典算法之直接插入排序及其优化
- 排序算法三:二分插入排序
- 经典算法之直接插入排序(三种实现)
- 经典算法之插入排序
- 经典算法之插入排序
- 我的Java开发学习之旅------>Java经典排序算法之二分插入排序
- 经典算法:二分查找、插入排序、选择排序、冒泡排序
- 经典算法:二分查找、插入排序、选择排序、冒泡排序
- 经典算法:二分查找、插入排序、选择排序、冒泡排序
- 经典算法(三):插入排序
- 排序算法之插入排序以及二分插入排序
- 经典排序算法之插入排序
- C--经典算法之排序---插入排序
- 经典算法学习:排序之插入排序
- 经典排序算法之直接插入排序
- 经典排序算法之插入排序
- 经典算法之二:冒泡排序及优化
- (一)linux C语言TCP服务端/客户端简单编程步骤
- Java基础 - 枚举介绍
- Spring Boot学习
- 【AI每日播报】强化学习可能会出错 OpenAI解读错误奖励函数问题和应对方法
- CSS:z-index空间位置
- 经典算法之三:插入排序及二分优化
- (转)空格在HTML中的表示方法( 含义)
- 理解RESTful架构 -- 作者: 阮一峰 日期: 2011年9月12日
- 导弹拦截
- 预防中文在mysql数据库乱码以及网页
- MyBatis(1)入门
- java实现gui界面的文件复制
- html标签的嵌套规则
- ios 约束(三)