插入排序是最简单的排序算法之一,是排序算法的基础。如果需要排序的元素数量很少,插入排序的速度很快,但是随着元素数量的增多,它的速度明显减慢。它的最坏情形运行时间是O(N2)。关于它的算法分析请参阅本文末尾的参考资料。
现在我们通过一个例子来看看插入排序的过程。假设要把5个整数(85, 40, 79, 80, 92)从小到大排列。
整个排序过程就是这样,如果完全按照上述过程来写程序,就需要两个数组,一个用来储存排序前的数列,一个用来储存排序后的数列。下面的 insertsort() 函数对这个过程作了一点小改进,只用一个数组和一个整型变量就可以了。
下面我们用C语言实现这个过程。
#include <stdio.h>
#include <stdlib.h>
#define MAX 10 // 要排序的元素个数
void insertsort(int A[], int N);
void printarray(int A[]);
int main()
{
int i, s[MAX];
for (i = 0; i < MAX; i++) // 用随机函数产生MAX个整数
s[i] = 1+(int) (100.0*rand()/(RAND_MAX+1.0));
printf("before:"); // 排序前
printarray(s);
insertsort(s, MAX); // 排序
printf("after :"); // 排序后
printarray(s);
return 0;
}
void printarray(int a[])
{
int i;
for (i = 0; i < MAX; i++)
printf(" %3d", a[i]);
printf("\n");
}
/* [CLRS] Chapter 2.1 */
void insertsort(int A[], int n)
{
int i, j, key;
for (j = 1; j < n; j++) // 注意C语言数组下标从0开始,A[1]是第二个元素
{
key = A[j];
i = j - 1;
while (i >= 0 && A[i] > key)
{
A[i+1] = A[i];
--i;
}
A[i+1] = key;
}
}
上面的 insertsort() 函数是用 Introduction to Algorithms(算法导论)的伪代码直接改写而成的。下面再提供另一种大同小异的写法,出自 Data Structures and Algorithm Analysis in C(数据结构与算法分析--C语言描述)。
/* [Mark Allen Weiss] p.166 图 7-2 */
void insertsort(int a[], int n)
{
int j, p;
int temp;
for (p = 1; p < n; p++) {
temp = a[p];
for (j = p; j > 0 && a[j-1]>temp; j--)
a[j] = a[j-1];
a[j] = temp;
}
}
如果原始数据本来就是正确排序的(例如 1, 2, 3, 4, 5),那么插入排序的运行时间是O(N),如果原始数据大部分已经排序(例如 1, 2, 4, 3, 5),那么插入排序的速度也很快,因为需要移动的数据很少。--这是插入排序的一个重要的特点!希尔排序(Shell Sort)就是基于这个事实对插入排序进行改进的一个非常成功的算法。
参考资料:
欢迎对本文发表评论,请把你的想法发送至kikistar.com@gmail.com,我会根据你的意见不断改善本文。