插入排序

来源:互联网 发布:监控windows进程排名 编辑:程序博客网 时间:2024/06/06 18:55

插入排序的思想

来自算法导论的解释
插入排序就好比平时我们打牌一样,把从牌堆里接到的一张牌插入到已经排好序的手牌中.
步骤如下:
1.牌堆里接到一张牌
2.从手牌的末端开始与已经排好序的手牌比较.
3.找到一个位置,这个位置的手牌比接到的牌大且该位置的前一个牌(如果有的话)比该牌小.
4.将该牌插入到该位置.

面临的问题

算法的描述很简单,但是用代码实现该算法面临一个问题:
Q:找到了该位置,如何处理比该牌大的牌,也就是说,要对数组进行插入排序,首当其冲的问题是如何处理那些比当前数大的那些数?
A:因为我们假设是将该元素插入的已经排好序的数组中,所以处理非常简单,就是将这些比它大的那些元素向后移动。

void insertionSort (int *array, int len) {    int i, j;//两个循环变量    int curNum;//待排序数,即当前未被排序的最小数组下标对应的数    if (len <= 1)//平凡情形退出该函数        return;    for (i = 1; i < len; i++) {//我们从数组的第二个元素开始比较,因为至少前面有牌才有比较的必要        curNum = array[i];//curNum记录当前待比较的数        for (j = i - 1; j >= 0 && array[j] > curNum; j++)//此步对应:从手牌的末端比较将要插入的手牌            //关键的步骤:我们把比当前元素大的元素向后移动                array[j + 1] = array[j];        array[j + 1] = curNum;/*这一步我想了很长时间,实际上画个图很容易明白,假如我们最里层的循环语句停止时:找到了一个数它小于curNum,此元素的位置为j,那么j+1就是待插入位置(即目的位置)*/    }}

算法正确性的证明

见:http://blog.csdn.net/chaoshd/article/details/54669757“>插入排序证明引发的对于循环不变式的定义

时间复杂度分析

设T(n)表示输入数组长度为n时最坏的运行时间那么
T(n) = T(n - 1) + a(n - 1) + b(n -1)
其中a是比较所花费的时间, b是移动所花费的时间。
令c/2 = max (a, b)
得T(n) = T(n) + c(n -1)从该式解得的T(n)表达式一定是原T(n)的上界,解这个式子:
T(n) - T(n-1) = c(n - 1)

T(2) - T(1) = c
连加得T(n) = O(n^2);

0 0