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

希尔排序

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

实现

希尔排序是对直接插入排序的一个优化,希尔排序分为预排和正式排序两个阶段,预排是把n个数分成gap组,每个组执行一遍直接插入排序,但是每次end不再是end--或者end+1,而是end-=gap和aend+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;
		}
	}				
}
相关推荐
楚识科技3 小时前
票据 OCR 识别技术深度解析:从算法原理到企业级落地实现
算法·ocr
longlongzihan3 小时前
LeetCode 25. K 个一组翻转链表 (迭代+分组反转法)
算法·leetcode·链表
xuxigifxfh3 小时前
牛客:BISHI8 大整数哈希
java·算法·哈希算法
涉密IT资质笔记3 小时前
涉密资质投入产出分析模型:时间成本、四块成本构成与 ROI 决策框架
java·开发语言·算法
木井巳4 小时前
【BFS 解决拓扑排序】火星词典
java·算法·leetcode·广度优先·宽度优先·图搜索算法
北风toto4 小时前
KMP 算法详解:从暴力匹配到 O(n+m) 的字符串搜索
java·开发语言·算法
沫璃染墨4 小时前
《从零入门数据结构与算法(二):线性表详解——从顺序表原理到静态与动态实现》
c语言·数据结构·顺序表
林澈在路上4 小时前
哪个写歌软件可以用自己声音?MELO音乐详解
人工智能·python·算法
爱读书的小胖4 小时前
Codewars Sum of a Sequence Hard Core Version C 解题分析
c语言·数据结构·算法
不会就选b4 小时前
算法日常・每日刷题--<动态规划>24
算法·动态规划