插入排序----希尔排序

希尔排序

希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个gap 组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工 作。当到达 =1 时,所有记录在统一组内排好序

实现

希尔排序是对直接插入排序的一个优化,希尔排序分为预排和正式排序两个阶段,预排是把n个数分成gap组,每个组执行一遍直接插入排序,但是每次end不再是end--或者end+1,而是end-=gap和a[end+gap]=tmp。

gap我们初始给它赋值为n,也就是分成n组,每组一个数,这样的话也就相当于直接插入排序,因为直接插入排序我们是每次挪一个位置和Tmp比较。

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

上述操作也就是把直接插入排序的1换成了gap而已,而这也就相当于gap等于1时候的预排,如果这样操作的话就和直接插入排序没有任何区别,所以我们把gap=n后,第一次预排之前要 gap=gap/3+1;这个操作就是把n个数据分成3组,+1是为了保证让gap不为0,如果gap=2,2/3=0,那分成0组是什么意思?,我把n个数据分成3组进行一次预排,第一次预排之后,每一组肯定都是有序的,这时,gap再进行一次 gap=gap/3+1;也就是再把他划分为更少的组,而我们使gap=gap/3+1,这个加1还有最重要的目的就是一定会使gap=1,所有我们当gap=1时不再往下划分Gap,这个时候就是正式排序

复制代码
void ShellSort(int* a, int n)//希尔排序
{
	int gap = n;
	while (gap > 1)
	{
		.......
	}				
}

gap越小,分的组越少,预排的结果越接近有序的。当gap>1时,进行的是预排序,当gap==1,进行的是正式排序。这就是希尔排序。

测试

复制代码
#include<stdio.h>
int main()
{
	
	int a[] = { 6,1,2,7,9,3,4,5,10,8 };
	int n = sizeof(a) / sizeof(a[0]);
	ShelltSort(a, n);
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	return 0;
}

时间复杂度

希尔排序的时间复杂度非常难计算,我们只需要记住它大概在O(N^1.3)左右就可以了。

性能测试

我们使用c语言随机生成的随机数,对这两个排序进行性能测试,我们测试的是1000000个随机数,(由于C语言生成的随机数只能有30000多个,所以我们在每个随机数后面再加上第几次循环的i可以大大减少重复的数据)

复制代码
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
srand(time(0));
const int N = 1000000;
int* a1 = (int*)malloc(sizeof(int)*N);
int* a2 = (int*)malloc(sizeof(int) * N);
for (int i = 0; i < N; i++)
{
	a1[i] = rand()+i;
	a2[i] = a1[i];
	
}
int begin1 = clock();
InsertSort(a1, N);
int end1 = clock();

int begin2 = clock();
ShellSort(a2, N);
int end2 = clock();

printf("InsertSort:%d\n", end1 - begin1);
printf("ShellSort:%d\n", end2 - begin2);

free(a1);
free(a2);

结果如上,由此可以看出,希尔排序无非就是比直接插入排序多了多次预排,直接的差异竟然如此之大。

源代码

复制代码
void ShellSort(int* a, int n)//希尔排序
{
	int gap = n;
	while (gap > 1)
	{
		gap = gap/3+1;//+1保证最后一次gap为1,也就是进行直接插入排序;gap越小,预排的结果越接近有序
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (a[end] > tmp)
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
	}				
}
相关推荐
野渡拾光30 分钟前
【考研408数据结构-05】 串与KMP算法:模式匹配的艺术
数据结构·考研·算法
tainshuai3 小时前
用 KNN 算法解锁分类的奥秘:从电影类型到鸢尾花开
算法·分类·数据挖掘
Coovally AI模型快速验证8 小时前
农田扫描提速37%!基于检测置信度的无人机“智能抽查”路径规划,Coovally一键加速模型落地
深度学习·算法·yolo·计算机视觉·transformer·无人机
pusue_the_sun8 小时前
数据结构:二叉树oj练习
c语言·数据结构·算法·二叉树
RaymondZhao349 小时前
【全面推导】策略梯度算法:公式、偏差方差与进化
人工智能·深度学习·算法·机器学习·chatgpt
zhangfeng11339 小时前
DBSCAN算法详解和参数优化,基于密度的空间聚类算法,特别擅长处理不规则形状的聚类和噪声数据
算法·机器学习·聚类
啊阿狸不会拉杆10 小时前
《算法导论》第 32 章 - 字符串匹配
开发语言·c++·算法
小学生的信奥之路10 小时前
洛谷P3817题解:贪心算法解决糖果分配问题
c++·算法·贪心算法
你知道网上冲浪吗11 小时前
【原创理论】Stochastic Coupled Dyadic System (SCDS):一个用于两性关系动力学建模的随机耦合系统框架
python·算法·数学建模·数值分析
地平线开发者13 小时前
征程 6 | PTQ 精度调优辅助代码,总有你用得上的
算法·自动驾驶