算法中有各种排序,然而真正踏踏实实的,认真理解和掌握的,真是不是特多,现在工作,已经是学以致用,但是,算法基础还是很重要的,所以最近在看算《算法导论》这本书,学习之余,也一步步把各种算法,罗列一些,最后再做个比较,后面一段时间,会集中精力深入研究下算法导论。
1.插入排序
是有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但是要求插入后此数据序列仍然有序。插入排序的基本操作就是讲一个数据插入到已经排好序的数据中,从而得到一个新的,个数甲乙的有序数据。
算法适合于少量数据的排列,时间复杂度O(n^2)。
2.内部排序和外部排序
根据排序过程中涉及的存储器不同,可以将排序方法分为两大类:一类是内部排序,指的是待排序的几率存放在计算机随机存储器中进行的排序过程;另一类的外部排序,指的是排序中要对外存储器进行访问的排序过程。
内部排序是排序的基础,在内部排序中,根据排序过程中所依据的原则可以将它们分为5类:插入排序、交换排序、选择排序、归并排序和基数排序;根据排序过程的时间复杂度来分,可以分为三类:简单排序、先进排序、基数排序。
评价排序算法优劣的标准主要是两条:一是算法的运算量,这主要是通过记录的比较次数和移动次数来反应;另一个是执行算法所需要的附加存储单元的的多少。
3.分类
包括:直接插入排序,二分插入排序(又称折半插入排序),链表插入排序,希尔排序(又称缩小增量排序)。属于稳定排序的一种(通俗地讲,就是两个相等的数不会交换位置) 。
4.原理
将n个元素的数列分为已有序和无序两个部分,如
插入排序过程示例
插入排序过程示例
下所示:
{{a1},{a2,a3,a4,…,an}}
{{a1⑴,a2⑴},{a3⑴,a4⑴ …,an⑴}}
…
{{a1(n-1),a2(n-1) ,…},{an(n-1)}}
每次处理就是将无序数列的第一个元素与有序数列的元素从后往前逐个进行比较,找出插入位置,将该元素插入到有序数列的合适位置中。
假设在一个无序的数组中,要将该数组中的数按插入排序的方法从小到大排序。假设啊a[]={3,5,2,1,4};插入排序的思想就是比大小,满足条件交换位置,一开始会像冒泡排序一样,但会比冒泡多一步就是交换后(a[i]=a[i+1]后)原位置(a[i])会继续和前面的数比较满足条件交换,直到a[i+1]前面的数组是有序的。比如在第二次比较后数组变成a[]={2,3,5,1,4};
5.设计步骤
算法设计有很多方法。插入排序使用的是增量(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]是局部有序的,保证了插入过程的正确性.
#include <stdio.h>
#define Num 10
int main(int argc, const char * argv[]) {
int arr[] = {1,12,3,5,7,9,12,16,21,23};
int count = sizeof(arr)/sizeof(arr[0]);
for (int i = 0; i <count; i++) {
int j = i;
int temp = arr[i];
while (j > 0 && temp < arr[j-1]) { //大于0防止越界,写在&&前面
arr[j] = arr[j-1];
j--;
}
arr[j] =temp;
}
for (int i = 0; i <count; i++) {
printf("[%2d]:%d\n",i ,arr[i]);
}
return 0;
}
PS:附:效率分析
稳定
空间复杂度O(1)
时间复杂度O(n2)
最差情况:反序,需要移动n*(n-1)/2个元素
最好情况:正序,不需要移动元素
数组在已排序或者是“近似排序”时,插入排序效率的最好情况运行时间为O(n);
插入排序最坏情况运行时间和平均情况运行时间都为O(n2)。
通常,插入排序呈现出二次排序算法中的最佳性能。
对于具有较少元素(如n<=15)的列表来说,二次算法十分有效。
在列表已被排序时,插入排序是线性算法O(n)。
在列表“近似排序”时,插入排序仍然是线性算法。
在列表的许多元素已位于正确的位置上时,就会出现“近似排序”的条件。
通过使用O(nlog2n)效率的算法(如快速排序)对数组进行部分排序,
然后再进行选择排序,某些高级的排序算法就是这样实现的。
从上述分析中可以看出,直接插入排序适合记录数比较少、给定序列基本有序的情况