排序算法01-插入排序
1. 基本思想
插入排序是对少量元素进行排序的有效算法。插入排序的过程很简单,将待排序的表List分成已排序和未排序的两个部分(如图1所示),将未排序中的元素依次插入已排序的表中。具体做法是取出未排序表中的一个元素,将之与已排序的表中元素依次进行比较,直至找到正确位置。则将该元素插入到该位置,重复这个步骤,直至未排序中元素全部插入已排序的表中。
(图1)
2. 算法实现
这里使用模板来实现,以增强代码的实用性。
1 template<class T> 2 void insert_sort(T* a,int n) 3 { 4 for(int i=1;i<n;i++) 5 { 6 T key=a[i]; 7 // insert key(namely a[i]) into the sorted sequence a[0..i-1] 8 int j=i-1; 9 while(key<a[j] && j>=0) 10 { 11 a[j+1]=a[j]; 12 j--; 13 } 14 a[j+1]=key; 15 } 16 }
3. 算法分析
3.1 算法可行性(循环不变式):
初始条件:在算法开始时,将要排序的表分割成A[0]和A[1..n-1].而左边的表A[0]为已排序的表,A[0]中只包含一个元素,显然成立,右边A[1..n-1] 为未排序的表。
保持:在两层循环中,目的是将元素A[i]插入到A[0..i-1]的正确位置中。它将从A[j-1]开始依次与已排序中的元素进行比较,直至找到一个位置k使得A[j-1]>=A[k]或者已经找到已排序的表头为止。然后将该元素插入到该位置。然后将i+1,开始下一次的插入。
终止:在内层循环中,当A[i]插入到已排序的表中终止内层循环。在外层循环中,当所以未排序的表的元素都插入到已排序的表中,即i=n时,算法终止。终止时,已排序的表长为n,未排序的表长为0,表明已将A[0..n-1]排完序。
3.2 时间复杂度
最坏情况:O(n^2);
最好情况:O(n)。
当输入的待排序的序列已经排好序,则只需要进行n-1比较就可以完成排序。故最好的情况下,算法的复杂度为O(n)。当输入的待排序的序列为完全逆序,即由大到小排列时,需要进行1+2+3+...+n-1=0.5n(n-1)次比较才可以完成排序。故最坏情况下,算法复杂度为O(n^2)。其他情况介于这两种情况之间。
3.3 空间复杂度
插入排序是在原数组的基础上进行的排序,我们称之为原地排序(即只有常数个元素被存放到数组以外的空间中去)。可见插入排序对内存的使用率还是很高的,不会白白浪费内存空间。所以它的空间复杂度为O(n).
3.4 利用概率论知识分析插入排序算法
待续。。。