数据结构图文解析之:直接插入排序及其优化(二分插入排序)解析及C++实现
0. 数据结构图文解析系列
1. 插入排序简介
插入排序是一种简单直观的排序算法,它也是基于比较的排序算法。它的工作原理是通过不断扩张有序序列的范围,对于未排序的数据,在已排序中从后向前扫描,找到相应的位置并插入。插入排序在实现上通常采用就地排序,因而空间复杂度为O(1)。在从后向前扫描的过程中,需要反复把已排序元素逐步向后移动,为新元素提供插入空间,因此插入排序的时间复杂度为O(n^2);
2. 直接插入排序图解
一般来说,插入排序都采用在数组上就地排序实现。具体算法描述如下:
- 从第一个元素开始,该元素可以认为已经被排序
- 取出下一个元素,在已经排序的元素序列中从后向前扫描
- 如果该元素(已排序)大于新元素,将该元素移到下一位置
- 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
- 将新元素插入到该位置后
- 重复步骤2~5
假设我们要对数组{12,4,5,2,6,14}进行插入排序,排序过程为:

2.1. 代码实现
template <typename T>
void InsertSort(T array[],int length)
{
if (array == nullptr || length < 0)
return;
int i, j;
for (i = 1; i < length; i++)
{
if (array[i]<array[i - 1])
{
int temp = array[i];
for (j = i - 1; array[j]>temp; j--) //元素后移
{
array[j + 1] = array[j];
}
array[j+1] = temp; //在合适的位置上出入元素
}
}
}
2.2. 复杂度分析
- 插入排序的最好情况是数组已经有序,此时只需要进行n-1次比较,时间复杂度为O(n);
- 最坏情况是数组逆序排序,此时需要进行n(n-1)/2次比较以及n-1次赋值操作(插入);
- 平均来说插入排序算法的复杂度为O(n^2)。
插入排序不适合对大量数据进行排序应用,但排序数量级小于千时插入排序的效率还不错,可以考虑使用。插入排序在STL的sort算法和stdlib的qsort算法中,都将插入排序作为快速排序的补充,用于少量元素的排序(通常为8个或以下)。
直接插入排序采用就地排序,空间复杂度为O(1).
2.3. 稳定性
直接插入排序是稳定的,不会改变相同元素的相对顺序。
3. 二分查找插入排序
上面的插入排序实现中,为了找到元素的合适的插入位置,我们采用从后到前遍历的顺序查找进行比较,为了减少比较的次数,我们可以换种查找策略:采用二分查找。
我们定义一个二分查找函数,函数返回插入位置的下标:
/*二分查找函数,返回插入下标*/
template <typename T>
int BinarySearch(T array[], int start, int end, T k)
{
while (start <= end)
{
int middle = (start + end) / 2;
int middleData = array[middle];
if (middleData > k)
{
end = middle - 1;
}
else
start = middle + 1;
}
return start;
}
//二叉查找插入排序
template <typename T>
void InsertSort(T array[], int length)
{
if (array == nullptr || length < 0)
return;
int i, j;
for (i = 1; i < length; i++)
{
if (array[i]<array[i - 1])
{
int temp = array[i];
int insertIndex = BinarySearch(array, 0,i, array[i]);//使用二分查找在有序序列中进行查找,获取插入下标
for (j = i - 1; j>=insertIndex; j--) //移动元素
{
array[j + 1] = array[j];
}
array[insertIndex] = temp; //插入元素
}
}
}
3.2. 复杂度分析
我们这个二分查找的算法并不会因为等于某一个值而停止查找,它将查找整个序列直到start<=end条件不满足而得到插入的位置,所以对于长度为n的数组来说,比较次数为log2n ,时间复杂度为O(log2n)。二分插入排序的主要操作为比较+后移赋值,则:
- 最坏情况:每次都在有序序列的起始位置插入,则整个有序序列的元素需要后移,时间复杂度为O(n^2)
- 最好情况:待排序数组本身就是正序的,每个元素所在位置即为它的插入位置,此时时间复杂度仅为比较时的时间复杂度,为O(log2n)
- 平均情况:O(n^2)
空间复杂度上, 二分插入排序也是就地排序算法,它的空间复杂度为O(1).
3.3. 稳定性
二分插入排序是稳定的。元素的相对顺序在排序后不会被改变。
原创文章,转载请注明: http://www.cnblogs.com/QG-whz/p/5194569.html
数据结构图文解析之:直接插入排序及其优化(二分插入排序)解析及C++实现的更多相关文章
- 数据结构图文解析之:哈夫曼树与哈夫曼编码详解及C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
- 数据结构图文解析之:数组、单链表、双链表介绍及C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
- 数据结构图文解析之:栈的简介及C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
- 数据结构图文解析之:队列详解与C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
- 数据结构图文解析之:AVL树详解及C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
- 数据结构图文解析之:二叉堆详解及C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
- 数据结构图文解析之:树的简介及二叉排序树C++模板实现.
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
- 前端优化:DNS预解析提升页面速度
在网页体验中我们常会遇到这种情况,即在调用百度联盟.谷歌联盟以及当前网页所在域名外的域名文件时会遇到请求延时非常严重的情况.那么有没有方法去解决这种请求严重延时的现象呢? 一般来说这种延时的原因不会是 ...
- 数据结构复习:直接插入排序与二分插入排序的C++实现
1.直接插入排序 直接插入排序的过程可以理解为一个固定长度的数组被分为两个集合,即已排序集合和未排序. 开始时已排序集合为空,而未排序集合即为整个数组.当排序开始后插入一个对象,已排序集合元素数目加1 ...
随机推荐
- UIWebView保存网页中的图片(转载)
现在H5混合原生开发的方式越来越流行,也就要用到UIWebView控件.在开发过程中,我们可能会遇到一个需求,要求我们保存网页上的图片,当用户点击图片的时候,就可以让用户选择是否下载图片. 在系统自带 ...
- JAVA实现图片裁剪
/** * 裁剪图片 * @param src 源图片 * @param dest 裁剪后的图片 * @param x 裁剪范围的X坐标 * @param y 裁剪范围的Y坐标 * @param w ...
- php new self()和new static()
class A { public static function get_self() { return new self(); } public static function get_static ...
- Ubuntu16.04LTS国内快速源
一.源文件位置 备份并替换/etc/apt/sources.list的源内容: 二.更改源文件内容 sudo vi /etc/apt/sources.list deb http://mirrors.a ...
- C#:结构
1. 简单示例 // 定义结构 public struct Person { public string name; public int age; } class Program { static ...
- 浅谈Java中的Set、List、Map的区别(转)
对JAVA的集合的理解是想对于数组: 数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型),JAVA集合可以存储和操作数目不固定的一组数据. 所有的JAVA集合都位于 java ...
- WPF DEV控件-ChartControl用法
WPF常用的第三方控件集,DevExpress 下面介绍如何生成Chart界面: <dxc:ChartControl AnimationMode="OnDataChanged" ...
- 如何使用 Entity Framework 构造动态查询表达式
一般的程序员做上几年以后, 或多或少的都有些代码的积累, 我也不例外. 作为微软技术程序员, 自从Linq和EF出来之后, 就基本上爱不释手了, 且不说执行效率的问题, 单单就开发效率和代码的可移植性 ...
- VS2013问题与解决方法
问题: Getting Error "'Microsoft.VisualStudio.Editor.Implementation.EditorPackage' package did not ...
- UVA11324 The Largest Clique[强连通分量 缩点 DP]
UVA - 11324 The Largest Clique 题意:求一个节点数最大的节点集,使任意两个节点至少从一个可以到另一个 同一个SCC要选一定全选 求SCC 缩点建一个新图得到一个DAG,直 ...