插入排序的C实现
参考动画:各种排序动画
原理:
将数组分成两个部分:左边为排好序的,右边为未排好序的部分
(但注意,排好序部分只是代表元素按照从小到大的顺序排,如果在未排序部分遇到了更小的元素,则可能发生替换)
将未排序部分的第一个元素取出,作待排元素,与排好序部分的最后一个元素比较大小,若比他大,则将未排序的那个元素插在它后面;如果比它小,则再往前比较。
实现思路
外层循环:i指向未排序的第一个元素,依次递增
内层循环:j指向已排序的最后一个元素,将此i与j指向的元素比较,依次递减、依次比较。
当然不要忘记了用于替换的temp元素。
注意:若此i待排元素插入,则在此之后的所有元素都要进行后移,此次操作我们可以在内层循环中完成,不需要再建循环。
实现代码
//按顺序输出数组元素
void trace(int A[],int N){
int i;
for(i= 0;i < N;i++){
if(i >0)printf(" ");//在相邻元素之间输入空格
printf("%d",A[i]);
}
printf("\n");
}
//插入排序
void insertionSort(int A[],int n){
int i,j,temp;
for(i = 1;i < n;i++){
temp = A[i];//将i指向的数取出,方便替换
j = i-1;
while(j >= 0 && temp < A[j] ){//如果待排元素<已排元素
A[j+1] = A[j];//开始后移,将已排元素的最后一个替换到此i所指的位置,即j+1
j--;//前面继续后移
}
A[j+1] = temp;//再将待排元素进行替换,至此完成一次排序。
trace(A,n);//输出
}
}
int main(){
int n,i;
int A[100];
scanf("%d",&n);
for(i = 0;i<=n;i++)scanf("%d",&A[i]);
trace(A,n);
insertionSort(A,n);
return 0;
}
时间复杂度分析
在最坏的情况下,每个i循环都要执行i次移动,共需要1+2+···+(n-1)=(n²-n)/2次移动,忽略常数项,复杂度为O(n²)。
输入数据能够大幅影响插入排序的效率,如果待排序数列为降序,则是O(n²);但如果待排序列已经为升序,则该序列从头到尾都不需要移动,只需O(n)。所以,插入排序法的优势就在于能快速处理相对有序的数据。