【排序】直接插入排序

直接插入排序
定义直接插入排序是一种最简单的排序方式,因此也被称为简单插入排序
基本思想:第i趟排序将序列中的第i+1个元素ki+1插入到一个已经按有序的子序列(k1,k2,···,ki)中的合适的位置,使得插入后的序列仍然保持按值有序
有这样一个数据元素序列{3,6,4,2,11,10,6’},其中6’表示该元素与本序列中的其他元素有重复,在此加以区分。
①首先该序列中已存在一个有序的子序列。
       {(3,6),4,2,11,10,6’}
②接下来要将4插入到这个子序列中,得到一个含有3个元素的有序的子序列。首先应当判断4应当插入的位置,然后才能进行插入。具体方法是,从元素6开始向左查找。因为4小于6,因此应当将元素6向后移动因为元素4大于元素3,因此将4插入到3和6之间。这样在原序列中得到一个按值有序的子序列。
       {(3,4,6),2,11,10,6’}
上述这个插入过程成为一趟直接插入排序。
按照这种插入的方法,可将后续4个元素逐一插入到前面的子序列中,形成新的子序列。当子序列与原序列长度一样时,插入排序结束。
在进行第1趟的插入排序时,可将第1个元素看成长度1,按值有序的子序列,然后将第2个元素插入到这个子序列中。以此类推,第i趟排序将序列中的第i+1个元素ki+1插入到一个已经按值有序的子序列(k1,k2,···,ki)中的合适的位置,使得插入后的序列仍然保持按值有序。
上述元素序列{3,6,4,2,11,10,6’}的直接插入排序过程如下图所示:
      开始状态:{(3),6,4,2,11,10,6’}
            ↓
      第1趟排序:{(3,6),4,2,11,10,6’}  
            ↓
      第2趟排序:{(3,4,6),2,11,10,6’}
            ↓
      第3趟排序:{(2,3,4,6).11.10.6’}
            ↓
      第4趟排序:{(2,3,4,6,11),10,6’}
            ↓
      第5趟排序:{(2,3,4,6,10,11),6’}
            ↓
      第6趟排序:{(2,3,4,6,6’,10,11)}
从这个插入排序的过程中可以看出:一个包含有n个元素的序列,需要n-1趟的直接插入排序就可以将原序列排列有序。直接插入排序的算法描述如下:

void sort(keytype k[],int n)
{
 	int i,j;
 	keytype tmp;
 	for(i=2;i<=n;i++)
 	{
   		tmp=k[i];//将k[i]保存在临时变量tmp中 
  		j=i-1;
  		while(j>0&&tmp)//找到tmp的插入位置 
   			k[j+1]=k[j--];//将k[j]后移,再将j减1 
  		k[j+1]=tmp;//将元素tmp插入到指定位置,第i-1趟插入完成 
 	}
}

通过上面的算法可以看出,将元素k[i]=tmp插入到子序列k[1]~k[i-1]中时要进行一系列的比较,将比k[i]大的元素向后移动,直到找到比k[i]小的第一个元素为止,将k[i]=tmp插入到这个元素的前面。因此本算法的功能是将序列从小到大递增排列。也可模仿该算法设计出从大到小的排列算法。
在本算法中,数据序列用一个keytype类型的数组k[]存放,第一个元素k[0]没有使用。因此在算法中可以省却掉临时变量tmp,用k[0]存储每次待插入的元素k[i],这样就节省了系统的空间开销。因为keytype类型的大小是不一定的。
【实例】
编写一个C程序,实现数据序列{2,5,6,3,7,8,0,9,12,1}的直接插入排序,要求从大到小,并输出排序后的数列元素。
【分析】
该数据序列包含10个元素,因此可以将它放到一个含有11个单元的数组中,第0号元素作为存放每次待插入的元素k[i]的空间,在这里不能直接照搬前面给出的算法,要将前面实现从小到大排列的算法加以修改,从而达到从大到小排列的目的。

#include<stdio.h>
sort(int a[],int n)//直接插入排序 
{
	int i,j;
 	for(i=2;i<=n;i++)
 	{
  		a[0]=a[i];
  		j=i-1;
  		while(j>0&&a[0]>a[j])
  		//改变判断条件,实现从大到小的排列 
   			a[j+1]=a[j--];
  		a[j+1]=a[0];//将元素a[0]插入到指定位置 
 	}
}
main()
{
 	int i,a[11]={-111,2,5,6,3,7,8,0,9,12,1};
 	//初始化序列,a[0]可任意赋值 
 	printf("原序列为:\n");
 	for(i=1;i<=10;i++)//显示原序列中的元素 
  		printf("%d ",a[i]);
 	sort(a,10);//插入排序 
 	printf("\n排序后的序列为:\n");
 	for(i=1;i<=10;i++)//输出排序后的结果 
  		printf("%d ",a[i]);
 	return 0;
}

运行结果为:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值