【算法】插入排序(从小到大) 排序范围(0~n-1)n为数组元素个数

   我们再来谈谈另外一个基本排序算法,插入排序。

  插入排序的思想也是十分简单。我们在排序范围(begin,end)中,选择数组下标为end的元素作为基准值,从它的前一个元素开始,向前遍历。在遍历过程中,把遍历到的值与基准值进行对比,如果比基准值,就把这个值后移,遍历下标i前移。直到找到一个元素,比基准值,或者遍历到数组头后结束,得到一个下标值,即插入位置。最后将基准值插入到这个下标值中。

  下面我们就进行算法分析吧,数据还是1 3 2 8 0 6 总共6个数

  

 1、第一趟,排序范围(0,1),遍历下标i指向end所指位置,即下标1,基准值为3


我们发现,a[i-1]=a[0]=1 < 3,不需要向前遍历,下标1即为插入位置

2、第二趟,排序范围(0,2),遍历下标i指向end所指位置,即下标2,基准值为2


我们发现,a[i-1] = a[1] = 3> 2,所以要将下标i前移,元素3后移,i指向1下标


a[i-1] = a[0] = 1 < 2,不需要向前遍历,下标1即为插入位置


3、第三趟,排序范围为(0,3),遍历下标i指向end所指位置,即下标3,基准值为8


我们发现,a[i-1] = a[2] = 3 < 8,不需要向前遍历,下标3即为插入位置


4、第四趟,排序范围为(0,4),遍历下标i指向end所指位置,即下标4,基准值为0


我们发现,a[i-1] = a[3] = 8> 0,所以要将下标i前移,元素8后移


a[i-1] = a[2] = 3> 0 ,所以要将下标i前移,元素3后移


a[i-1] = a[1] = 2> 0,所以要将下标i前移,元素2后移


a[i-1] = a[0] = 1> 0,所以我们要将下标i前移,元素1后移


此时,遍历指针i已经指向了数组头,即下标0,说明我是在遍历的所有元素中最小的,这时,下标0就是我们需要插入的位置


5、第五趟,排序范围为(0,5),遍历下标i指向end所指位置,即下标5,基准值为6


我们发现,a[i-1] = a[4] = 8> 6,所以要将下标i前移,元素8后移


a[i-1] = a[3] = 3 < 6,不需要向前遍历,下标4即为插入位置


经过以上5趟,排序结束,最终序列为


  从以上分析我们可以知道,要完成插入排序,要有个方法,一个用于找插入位置并且插入数据(核心),另外一个用于反复调用,扩大排序范围。与选择排序不同,插入排序是保持begin指针不动,由前往后扩大。而选择排序是保持end指针不动,由前往后缩小。以上图中的下标i,就是基准值要插入的位置!

  由此,我们可以得到插入排序算法核心(insert)与入口方法(sort)

#include <stdio.h>
#define Elemtype int
//插入排序核心
void insertion(Elemtype a[] , int begin , int end)
{
	//将待排序数组的最后一个元素作为基准值
	Elemtype base = a[end];
	//遍历指针i指向待排序数组的最后一个元素
	int i = end;
	//循环判断,退出条件为:1、i已经指向数组头 2、发现有比基准值小的元素
	while(i > 0 && a[i-1] > base)
	{
		//如果进入循环体,说明当前扫描值比基准值大,则应把基准值后移
		a[i] = a[i-1];
		//下标前移
		i--;
	}
	//找到插入位置后,将基准值插入
	a[i] = base;
}

void sort(Elemtype a[] , int begin , int end)
{
	int i;
	//从第一个元素开始,到最后一个元素为止,保持begin指针不动,逐渐扩大排序范围
	for(i = begin ; i <= end ; i++)
	{
		insertion(a,begin,i);
	}
}

完整可执行程序如下

#include <stdio.h>
#define Elemtype int
//插入排序核心
void insertion(Elemtype a[] , int begin , int end)
{
	//将待排序数组的最后一个元素作为基准值
	Elemtype base = a[end];
	//遍历指针i指向待排序数组的最后一个元素
	int i = end;
	//循环判断,退出条件为:1、i已经指向数组头 2、发现有比基准值小的元素
	while(i > 0 && a[i-1] > base)
	{
		//如果进入循环体,说明当前扫描值比基准值大,则应把基准值后移
		a[i] = a[i-1];
		//下标前移
		i--;
	}
	//找到插入位置后,将基准值插入
	a[i] = base;
}

void sort(Elemtype a[] , int begin , int end)
{
	int i;
	//从第一个元素开始,到最后一个元素为止,保持begin指针不动,逐渐扩大排序范围
	for(i = begin ; i <= end ; i++)
	{
		insertion(a,begin,i);
	}
}

void display(Elemtype a[] , int begin , int end)
{
	int i;
	for(i = begin ; i <= end ; i++)
	{
		printf("%d ",a[i]);
	}
	printf("\n");
}

int main()
{
	Elemtype a[] = {1,3,2,8,0,6};
	printf("排序前:\n");
	display(a,0,5);
	sort(a,0,5);
	printf("排序后:\n");
	display(a,0,5);
	return 0;
}

运行效果如下:


插入排序算法的时间复杂度也是O(n^2)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值