【C语言】【数据结构初阶】 插入排序 ,希尔排序 - 详解

一.插入排序

1.插入排序介绍

插入排序是指在待排序的元素中,假设前面n-1(其中n>=2)个数已经是排好顺序的,现将第n个数插到前面已经排好的序列中,然后找到合适自己的位置,使得插入第n个数的这个序列也是排好顺序的。 按照此法对所有元素进行插入,直到整个序列排为有序的过程,称为插入排序 。

2.代码

1.单趟排序(即插入一个数据)

以从小到大的排序为例。

        
int end; //end为原来的有序的序列的最后一个数字的下标
x = a[end + 1];  //x为需要插入的数据

while (end >= 0) 
{
//当x比序列的最后一个数字要小时,最后一个数字往后挪一个位置
//当x比序列的倒数第二个数也小时,倒数第二个数字也往后挪一个位置
//以此类推,直到x比某个数字大时,跳出循环
	if (a[end] > x)  
	{
		a[end + 1] = a[end];
		end--;
	}
	else
	{
    	break;
	}
}
//此时,如果x比原来的序列的所有数字都小,那么end为-1,end+1为0,即x会插入到a[0]的位置
//否则,x会插入到比x小的数字的后面,比x大的数字的前面
a[end + 1] = x;

这样我们就实现了将一个数字插入一个有序数列。

2.完整排序

那么,在实现了单趟排序的基础上,我们可以实现将一个无序的数组进行从大到小或者从小到大的排序。

我们还是以从小到大的排序为例。(要想实现从大到小,改变大于小于号即可)

void InsertSort(int* a, int n)
{
	assert(a);  //断言

	int end = 0;
	int x = 0;
	for (end = 0; end <= n - 2; end++)
	{
//当end为数组的倒数第二个元素时,x为数组的最后一个元素,所以end <= n - 2
		x = a[end + 1]; 
		while (end >= 0)
		{
			if (a[end] > x)
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;
			}
		}
		a[end + 1] = x;
	}
}

3.运行结果

二.希尔排序 

1.概念

希尔排序(Shell Sort)属于插入排序的一种,也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。

将一列数分为gap组,比如gap为3时,分组如下:

 将每一组内分别进行插入排序,gap为3时,即需要进行3次插入排序的过程。每一组插入排序结束后,其组内的数字就是升序。

比如:红箭头所指的一组:1  3  9;

蓝箭头所指的一组:2  5  6;

绿框的一组:4  7  8;

总的数列:1  2  4  3  5  7  9  6  8;

当gap组数据分别进行插入排序之后,该数列就变得更加相对有序了。

2.代码

//希尔排序
void ShellSort(int* a, int n)
{
	int gap = n;
	while (gap > 1)
	{
		gap /= 2;
//gap不断变小,直至为1

		int j = 0;
//将gap组数据分别进行插入排序
		for (j = 0; j < gap; j++)
		{
			int end = 0;
//一组数据的插入排序
			for (end = j; end < n - gap; end += gap)
			{

				int x = a[end + gap];
				while (end >= 0)
				{
					if (a[end] > x)
					{
						a[end + gap] = a[end];
						end -= gap;
					}
					else
					{
						break;
					}
				}
				a[end + gap] = x;
			}
		}
	}
}

3.代码略作改动

实质是:2中的代码是将gap组一组一组排序,而下面的代码中,则是按照顺序一个一个排序。

//希尔排序稍加改动(减少了循环嵌套,代码简化,但效率并未优化)
void ShellSort2(int* a, int n)
{
	int gap = n;
	while (gap>1)
	{
		gap /= 2;

		int i = 0;
		for (i = 0; i < n - gap; i++)
		{
			int end = i;
			int x = a[end + gap];
			while (end >= 0)
			{
				if (a[end] > x)
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = x;
		}
	}
}

4.运行结果

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杯酒问苍天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值