插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
简单小tips:假设一个数列:1、2、5、3。插入排序的思想就是从1开始每次向前遍历:
2比1大,为有序
5比2大,5比1大,为有序
3比5小,无序,交换,交换之后3与2比,3与1比有序
结果为 :1、2、3、5
算法步骤:
1)将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
2)从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
实现代码:重载插入排序的函数,一次的改进:二分法查找插入位置
/***************************************************************************
* @file main.cpp
* @author MISAYAONE
* @date 24 March 2017
* @remark 24 March 2017
* @theme Insertion Sort
***************************************************************************/
#include <iostream>
#include <vector>
using namespace std;
//传入一对迭代器,标准的插入排序
void Insertion_sort(vector<int>::iterator begin,vector<int>::iterator end)
{
for (auto p1 = begin; p1 != end; ++p1)
{
auto p2 = p1;
while ((p2 != begin) && *(p2-1)>*p2)
{
int temp = *(p2);
*p2 = *(p2-1);
*(p2-1) = temp;
--p2;
}
}
}
//对函数进行重载,传入指向数组的指针和数组大小,同时进行第一次改进(也称二分插入排序)
void Insertion_sort(int a[],size_t size)
{
for (size_t i = 1; i != size; ++i)
{
int low = 0;//排好元素的下界
int high = i;//排好元素的上界
if (a[i-1] > a[i])//判断元素是否需要排序,满足条件则需要排序
{
int temp = a[i];//待排元素
a[i] = a[i-1];//直接先将排好元素中的最后一个元素后移一位
//while循环使用二分法找到插入位置
while (low <= high)
{
int mid = (low+high)/2;
if (temp < a[mid])//待排元素之前的序列肯定是有序的,找到其中位数比较大小
{
high = mid-1;
}
else
low = mid+1;
}
size_t j=i-1;
for(j;j>=high+1;j--)//移动元素
a[j+1]=a[j];
a[j+1] = temp;
}
}
}
int main(int argc, char **argv)
{
int a[10] = {2,5,6,3,1,4,8,7,9,0};
vector<int> vec(a,a+10);
Insertion_sort(vec.begin(),vec.end());
for (size_t i = 0; i < vec.size(); ++i)
{
cout<<vec[i]<<" ";
}
Insertion_sort(a,10);
cout<<endl;
for (size_t i = 0; i < 10; ++i)
{
cout<<a[i]<<" ";
}
cin.get();
return 0;
}
复杂度分析:
最优时间复杂度:当输入数组就是排好序的时候,复杂度为O(n),而快速排序在这种情况下会产生O(n^2)的复杂度。
最差时间复杂度:当输入数组为倒序时,复杂度为O(n^2)
插入排序比较适合用于“少量元素的数组”
插入排序的复杂度和逆序对的个数一样,当数组倒序时,逆序对的个数为n(n-1)/2,因此插入排序复杂度为O(n^2)。
特点分析:稳定算法(stable)、in place算法
例题1:请写出链表的插入排序程序:
template<typename T>
struct list_node
{
struct list_node<T> *next;
T value;
};
template<typename T>
struct _list
{
struct list_node<T> *head;
int size;
};
template<typename T>
void SortLink(struct _list<T> * link) {
struct list_node<T> *pHead,*pRear,*p,*tp;
if (!link) return;
for (pHead=link->head,pRear=0;pHead;pHead=pHead->next) {
for (tp=pHead,p=pHead->next;p;tp=p,p=p->next)
if (pHead->value>=p->value)
tp->next=p->next,p->next=pHead,pHead=p,p=tp;
if (!pRear) link->head=pHead;
else pRear->next=pHead;
pRear=pHead;
}
}