插入排序(insertion-sort)
输入:n个数的一个序列<a1,a2,...,an>.
输入:输入序列的一个排列<a'1,a'2,...,a'n>,满足a'≤a'2≤...a'n.
分类:包括:直接插入排序,二分插入排序(又称折半插入排序),链表插入排序,希尔排序(又称缩小增量排序)。属于稳定排序的一种(通俗地讲,就是两个相等的数不会交换位置) 。
插入排序的简单理解:工作原理是通过构建有序序列,对于未排序的数据,在以排序序列中从后向前扫描,找到相应的位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),通常就像许多人排序一手扑克牌。开始时,我们的左手并且桌子上的牌面向下。然后,我们每次从桌子上拿走一张牌并将它插入左手中正确的位置。为了找到一张牌的正确位置,我们从右到左将它已在手中的每张牌进行比较。拿在左手上的牌总是排序好的,原来这些牌是桌上牌堆中顶部的牌。(每一趟将一个待排序的记录,按照其关键字的大小插入到有序队列的合适位置里,知道全部插入完成。)
设计:
算法设计有很多方法。插入排序使用的是增量(incremental)方法;在排好子数组A[1..j-1]后,将A[j]插入,形成排好序的子数组A[1..j];
步骤
⒈从有序数列和无序数列{a2,a3,…,an}开始进行排序;
⒉处理第i个元素时(i=2,3,…,n),数列{a1,a2,…,ai-1}是已有序的,而数列{ai,ai+1,…,an}是无序的。用ai与ai-1,a i-2,…,a1进行比较,找出合适的位置将ai插入;
⒊重复第二步,共进行n-i次插入处理,数列全部有序。
思路
假定这个数组的序是排好的,然后从头往后,如果有数比当前外层元素的值大,则将这个数的位置往后挪,直到当前外层元素的值大于或等于它前面的位置为止.这具算法在排完前k个数之后,可以保证a[1…k]是局部有序的,保证了插入过程的正确性
插入排序算法的分析
过程INSERTION-SORT需要的时间依赖于输入:排序数量大的数比排序小的数需要更长的时间。此外,依据它们已被排序的程度,INSERTION-SORT可能需要不同数量的时间来排序两个具有相同的输入序列。
插入排序的伪代码如下:
voidinsert_sort(int*array,unsignedintn)
{
int i,j,temp;
for(i=1;i<n;i++)
{
temp=*(array+i);
for(j=i;j>0 && *(array+j-1)>temp;j--)
{
*(array+j)=*(array+j-1);
}
*(array+j)=temp;
}
}
c语言实现:
#include<stdio.h>
void insertionsort(int *arr,int len)
{
int i,j;
int temp;
for(i=1;i<len;i++)
{
temp= *(arr+i); //待插入数组取出第一个元素
for(j=i;j>0 && *(arr+j-1)>temp;j--)
{
*(arr+j)=*(arr+j-1);
}
*(arr+j)=temp;
}
}
int main()
{
int i=0;
int arr[6]={8,2,4,9,3,6};
insertionsort(arr,6);
for(i=0;i<6;i++){
printf("排序后的数字是:%d\n ", arr[i]);
}
return 0;
}
int i,j;
int temp;
for(i=1;i<len;i++)
{
temp= *(arr+i); //待插入数组取出第一个元素
for(j=i;j>0 && *(arr+j-1)>temp;j--)
{
*(arr+j)=*(arr+j-1);
}
*(arr+j)=temp;
}
}
int main()
{
int i=0;
int arr[6]={8,2,4,9,3,6};
insertionsort(arr,6);
for(i=0;i<6;i++){
printf("排序后的数字是:%d\n ", arr[i]);
}
return 0;
}
算法复杂度:
如果目标是把n个元素的序列升序排列,那么采用插入排序存在最好情况和最坏情况。最好情况就是,序列已经是升序排列了,在这种情况下,需要进行的比较操作需(n-1)次即可。最坏情况就是,序列是降序排列,那么此时需要进行的比较共有n(n-1)/2次。插入排序的赋值操作是比较操作的次数加上 (n-1)次。平均来说插入排序算法的时间复杂度为O(n^2)。因而,插入排序不适合对于数据量比较大的排序应用。