十大经典排序算法----希尔排序

 前言:希尔排序就是对插入排序的一种优化方法吧!

目录

希尔排序的思想

代码分析 

 完整代码


我第一次听到希尔排序这个名字的时候,哇塞,好高大上的样子。这就有点像高中数学,或者高数学的洛必达法则嘛(据说洛必达法则是洛必达花钱买来的嘛,我想表达啥意思,你自己拿捏哈。)希尔排序并没有想我想象的那么NB(哈哈,只是相对来说哈,这些排序算法是我发明不出来的),他就是对插入排序的优化。

希尔排序的思想

把待排序列分为多个组,然后再对每一组进行插入排序,从而让整个序列有一定的顺序,让后多次调整分组方式,使得序列进一步有序起来,最终达到排序的效果。

咱就得好好谈一谈这个希尔排序的分组问题,所谓分组,就是如何选取每组排序元素之间的间隔,只要按照一定的算法,使得最后一次排序时每组数据之间的间隔为零就行了。可能这样不好理解,咱看个示意图

通过每组数据的排序和增量的减少达到排序的目的。如上图第一次增量为7(至于为什么是元素个数除以2得到增量,这个只是其中的一种算法,你只要保证最后的增量为1即可),我们就以7为步长,即中间隔6个元素,选取数组元素分为一组,然后对每一组进行插入排序(颜色相同的即为每一组)。排序完成后减少步长(增量)进行第二次排序,直到步长(增量)为1后进行最后一次排序,最终达到排序效果。这就是希尔排序的精髓所在吧。因为希尔排序是通过缩小增量达到排序的效果,所以希尔排序也叫做缩小增量排序。

代码分析 

1. 希尔排序就是在插入排序之上套了几层循环,所以你肯定得先会插入排序。

i 就代表步长啦(没做到见名知义,抱歉啦),外层循环控制整体的排序次数,即增量减为1需要经历几次排序。内层循环控制每组的插入排序,步长(增量)为7,就有7组数据嘛。

//参数一:数组首元素地址,参数2:数组长度
void shell_sort(int* arr, int length)
{
	int i = 0;
	int j = 0;
	int flag = 0;
	//排序次数
	for (i = length / 2; i > 0; i = i / 2)
	{
		//每组进行插入排序
		for (j = 0; j < i; j++)
		{
			insert_sort(arr, length, j, i);
		}
	}
}

2. 每组的插入排序:与原来的插入排序不同咱需要四个参数:参数1:数组首元素地址,参数2:数组长度,参数3:每组数据开始的下标,参数4:步长。因为每个元素中间隔了步长-1个元素

所以循环的增量就是步长,要交换元素的下标也要加上步长,如果插入排序不懂,可以看看我前面写的内容。

//参数1:数组首元素地址,参数2:数组长度,参数3:每组数据开始的下标,参数4:步长
void insert_sort(int* arr, int length, int begin, int step)
{
	int i, j, k, m, l;
	int flag = 0;
	//比较的次数
	for (i = begin + step; i < length; i += step)
	{
		flag = arr[i];
		//每个元素的排序
		for (j = i - step; j >= 0; j-=step)
		{
			//不比前面的元素大停止循环
			if (arr[j] <= flag)
				break;
			//移位
			arr[j + step] = arr[j];
		}
		//插入
		arr[j + step] = flag;
	}
}

 完整代码

#include<stdio.h>
int main()
{
	int arr[15] = { 3,44,38,5,47,15,36,26,27,2,46,4,19,50,48 };
	int i = 0;
	int j = 0;
	int media;
	for (j = 1; j < 15; j++)
	{
		media = arr[j];
		for (i = j - 1; i >= 0; i--)
		{
			if (arr[i] <= media)
				break;
			arr[i + 1] = arr[i];
		}
		arr[i + 1] = media;
	}
	//打印数据
	int m = 0;
	for (m = 0; m < 15; m++)
	{
		printf("%d ", arr[m]);
	}
	return 0;
}


//参数1:数组首元素地址,参数2:数组长度,参数3:每组数据开始的下标,参数4:步长
void insert_sort(int* arr, int length, int begin, int step)
{
	int i, j, k, m, l;
	int flag = 0;
	//比较的次数
	for (i = begin + step; i < length; i += step)
	{
		flag = arr[i];
		//每个元素的排序
		for (j = i - step; j >= 0; j-=step)
		{
			//不比前面的元素大停止循环
			if (arr[j] <= flag)
				break;
			//移位
			arr[j + step] = arr[j];
		}
		//插入
		arr[j + step] = flag;
	}
}

//参数一:数组首元素地址,参数2:数组长度
void shell_sort(int* arr, int length)
{
	int i = 0;
	int j = 0;
	int flag = 0;
	//排序次数
	for (i = length / 2; i > 0; i = i / 2)
	{
		//每组进行插入排序
		for (j = 0; j < i; j++)
		{
			insert_sort(arr, length, j, i);
		}
	}
}

int main()
{
	int arr[15] = { 3,44,38,5,47,15,36,26,27,2,46,4,19,50,48 };
	int length = sizeof(arr) / sizeof(arr[0]);

	shell_sort(arr, length);
	//打印数组元素
	int m = 0;
	for (m = 0; m < length; m++)
	{
		printf("%d ", arr[m]);
	}
	return 0;
}

好啦,希尔排序就到这里,拜拜!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
十大经典排序算法是指在计算机科学中常用的排序算法,它们分别是: 1. 冒泡排序(Bubble Sort):重复地比较相邻的两个元素,将较大的元素逐渐向右移动。 2. 选择排序(Selection Sort):每次从未排序的部分选择最小(或最大)的元素,并放在已排序的部分的末尾。 3. 插入排序(Insertion Sort):将未排序的元素逐个插入到已排序的部分中的正确位置。 4. 希尔排序(Shell Sort):将待排序的数组按照一定步长进行分组,对每组进行插入排序,逐渐减小步长。 5. 归并排序(Merge Sort):将待排序的数组递归地分成两半,对每一半进行排序,然后合并两个有序数组。 6. 快速排序(Quick Sort):选择一个基准元素,将数组划分为两部分,左边部分都小于基准,右边部分都大于基准,递归地对两部分进行排序。 7. 堆排序(Heap Sort):将待排序的数组构建成一个最大堆(或最小堆),然后依次取出堆顶元素并调整堆结构。 8. 计数排序(Counting Sort):统计数组中每个元素出的次数,然后根据统计结果对元素进行排序。 9. 桶排序(Bucket Sort):将待排序的数组划分为多个桶,对每个桶中的元素进行排序,最后将桶中的元素按顺序合并。 10. 基数排序(Radix Sort):按照元素的位数,将待排序的数组从低位到高位进行排序。 以上是十大经典排序算法,每种算法都有其适用的场景和性能特点,选择合适的排序算法可以提高程序的效率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

姬如祎

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

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

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

打赏作者

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

抵扣说明:

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

余额充值