我觉着还是先把代码贴上,然后讲解会比较好
1. 插入排序
核心伪代码:
for j <- 2 to n
do key <- a[ j ]
while i>=o and key < a[ i ]
do a[ i + 1 ] <- a[ i ]
i <- i-1
a[ i +1 ] = key
C 实现代码:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <time.h>
void print_array_int(int* array,int n);
int main()
{
int n ; // the numbers of array A
int* a ; // the pointer of array A
int i,j ;
int key ;
printf("Please input the value of array A:");
scanf("%d",&n);
a = (int*)malloc(n*sizeof(int));
srand((int)time(0));
printf("Befor the order,the value of array A:\n");
for(i=0;i<n;i++)
{
*(a+i) = rand();
}
print_array_int(a,n);
<span style="BACKGROUND-COLOR: #ff6666">for(j=2;j<n;j++)
{
key = *(a+j);
i = j-1 ;
while(i>=0&&key<*(a+i))
{
*(a+i+1)=*(a+i);
i-- ;
}
*(a+i+1)=key;
}
</span> printf("\nAfter the order , the value of array A:\n");
print_array_int(a,n);
return 0;
}
void print_array_int(int* array,int n)
{
int i ;
for(i=0;i<n;i++)
{
printf("The %d of array is:%d\n",i,*(array+i));
}
}
真正核心的部分就是上面标红的地方
2. 插入排序原理讲解
Excell下做了个图表:
首先:我们假设,从0到j-1的元素都已经排好序了,现在对j号下表的元素进行排序。
先将 key = a[j] , 即将j号元素先赋值给一个变量
i = j - 1 ; 我们要将j号元素倒着向前比较,所以我们现将要比较的第一个元素即j-1赋值给i;
while( i >=0 && key < a[i] ) 即循环的条件是将j号变量的值key组个与a[i-1] ......a[0]比较,这里一定要注意是倒着来比较的,知道找到一个a[i] , 使key>=a[i]
a[ i+1 ] = a[ i ] . i-- ; 如果比较的位置不是j应该插入的位置,则将 i 号元素赋值给 i+1 号元素, 这里是直接覆盖,不要担心最后的那个元素,那个元素是j的位置,我们赋值给key,找它应该在的位置了。
当这个循环结束了,就满足条件:a<0 || key>=a[i] ; 如果是a<0则说明,这个j号元素不用动,直接加入到前面已经排好序的元素里面就可以了。如果是key>=a[i],则说明j号元素找到了应该插入的位置。直接插入。
3. 上面运行结果:
Linux下编译执行: gcc -o insert_order.exe insert_order.c
4. 性能分析:
我们知道一个算法的好坏,在保证正确率的前提下,是以平均运行时间来衡量的,也就是期望时间。
以概率统计中的知识,期望时间就是《 n种可能的输入(每种可能的输入出现的概率*这种输入执行的时间)再求和 》
这里我们做一种假设:没种可能输入的序列出现的可能性都相同,即1/n ;
而每次执行,外层循环j = 2 ---> n ; 内层循环 0 ------------- i (n)
即它执行的渐进性趋于:T(n^2) . 我们以后会以这个来和别的排序方法比较性能优劣。
注:插入排序,当输入的序列是正序的,性能最佳;当输入的序列是逆序的,性能最差。在数量较少时,插入排序的性能还是不错的,但是一旦数量很大,插入排序又是难以让人接收的。
算法分析= 数学的严谨+工程的直觉
算法分析学习第一节,一定要坚持下去