算法之排序——插入排序

插入排序的基本思想是,对数组元素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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值