插入排序的基本思想是,对数组元素a[l]~a[r],经过前i-l遍处理后,a[l],a[l+1],.....a[i-1]已排好序。下一轮处理就是要将a[i]插入到a[l],a[l+1],.......a[i-1]的合适位置,即插入到前面的有序数列中,使得a[l],a[l+1],........a[i]是排好序的序列。 要达到这个目的,可以用顺序比较的方法,首先比较a[i]和a[i-1];如果a[i-1]<=a[i],则 a[l]......a[i]已排好序,第i遍处理就结束了;否则交换 a[i]和a[i-1]的位置,继续比较a[i-1]和a[i-2],直到找到某个位置j(1<=j<=i-1),使得a[j]<=a[j+1]时为止。直接看代码会比较直观
c语言代码:
#include<stdio.h>
#include<malloc.h>//为了使用malloc函数
void insert(int *a,int l,int i)
{
int v=a[i]; //v为临时变量,存储要插入的数
while(i>l&&v<a[i-1]) //从后往前查找,在不越界的情况下,找到一个比V小的数,即前面的数比V大,后面的数比V小,则插入
{
a[i]=a[i-1];//后面的数依次往后挪一个位置,为空出一个位置,以便插入V
i--;
}
a[i]=v; //将V插入到相应位置
}
void insertion(int *a,int l,int r) //默认a[0]是有序的,然后从a[1]开始,每个元素都插入到前面已经排序好的元素中
{
int i;
for(i=1;i<=r;i++) //此循环就是将除a[0]外的每个元素依次插入到前面的有序数列中
insert(a,l,i); //调用插入函数
}
int main()
{
int *a; //声明一个int 型指针
int n=10,t,i;//n可以自由输入,此处定义n=10;
a=(int *)malloc(sizeof(int)*n); //动态分配一片n个int 的空间 , 即数组a[n];
for(i=0;i<n;i++) //输入n个数,并存储在数组中
scanf("%d",&a[i]);
insertion(a,0,n-1);//调用排序函数
for(i=0;i<n;i++) //打印排序之后的数组
printf("%d ",a[i]);free(a);
return 0;
}
哨兵方法:
上述程序在每次比较时,都要判断i是否越界,即i>0是否成立,这样显然有点麻烦,如果在a[0]设置一个哨兵的话,即可解决问题,但是数据的话就要从a[1]开始存。
#include<stdio.h>
#include<malloc.h>//为了使用malloc函数
void insert(int *a,int l,int i)
{
a[0]=a[i]; //设置哨兵,即a[0]存储的是要插入的元素,以下循环在遇到a[0]<a[0]的时候就会退出
while(a[0]<a[i-1]) //从后往前查找,在不越界的情况下,找到一个比V小的数,即前面的数比V大,后面的数比V小,则插入
{
a[i]=a[i-1];//后面的数依次往后挪一个位置,为空出一个位置,以便插入V
i--;
}
a[i]=a[0]; //将V插入到相应位置
}
void insertion(int *a,int l,int r) //默认a[0]是有序的,然后从a[1]开始,每个元素都插入到前面已经排序好的元素中
{
int i;
for(i=2;i<=r;i++) //默认a[1]为有序,此循环就是将除a[1]外的每个元素依次插入到前面的有序数列中,a[0]为哨兵,
insert(a,l,i); //调用插入函数
}
int main()
{
int *a; //声明一个int 型指针
int n=10,t,i;//n可以自由输入,此处定义n=10;
a=(int *)malloc(sizeof(int)*(n+1)); //动态分配一片n个int 的空间 , 即数组a[n];
for(i=1;i<=n;i++) //注意:由于要设置一个哨兵,所以只能从a[1]开始存数据
scanf("%d",&a[i]);
insertion(a,0,n);//调用排序函数,实参为数组下标0和n
for(i=1;i<=n;i++) //打印排序之后的数组
printf("%d ",a[i]);
free(a);
return 0;
}
在插入的过程需要比较以找到合适的位置插入,这时就可以才用二分查找的策略以减少查找次数;
代码如下:只是修改了查找部分
#include<stdio.h>
void insertion(int a[],int l,int i)
{
int v=a[i];
int r=i,m,j;
while(l<=r) //折半查找
{
m=(l+r)/2;
if(v==a[m])break;
if(v<a[m]) r=m-1;
if(v>a[m]) l=m+1;
}
for(j=i;j>m;j--) //m即要插入的位置,所以将m之后的元素一次往后挪,然后将a[i]插入m的位置
a[j]=a[j-1];
a[m]=v;
}
void sort(int a[],int l,int r)
{
for(int i=1;i<=r;i++)
insertion(a,0,i);
}
int main()
{
int a[10]={5,7,9,6,8,4,2,1,3,10};
printf("排序前:\n");
for(int i=0;i<10;i++)
printf("%d ",a[i]);
sort(a,0,9);
printf("\n排序后:\n");
for(i=0;i<10;i++)
printf("%d ",a[i]);
return 0;
}