希尔排序的实现

引言

排序在我们生活中十分常见,无论是购物软件中的商品推荐还是名次、排名都与排序算法息息相关。希尔排序是排序中较快的一种,而希尔排序实现的基础是插入排序。

排序的实现

插入排序(以升序为例)

插入排序的原理是从第二个数开始,与前面的数相比较,如果比前面的数大,则与其交换,并且此移动过程会一直持续直到前k(k为此次刚开始移动的数的位置)个数达到有序为止;否则不会移动。代码如下:

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

我们将一直要改变的那个数设为tmp,将它与前面的数(end)比较,如果tmp较小,则进行交换,先将啊aend 覆盖aend + 1,再--end达到tmp继续与前一个数比较的效果,最后达到效果.

希尔排序

希尔排序分为两步:预排序与插入排序.

预排序

预排序的目的是先让数组接近有序,将所有数据分为gap组,其代码与插入排序十分类似。

以该图为例,改预排序的流程是5与9比较,如果比9小,则将9放到原来5的位置,

再将8与9相比较并与5比较,8比9小,再将9放到8的位置,8比5大,所以再停止

最后将最后的5进行排序即可.

再嵌套一层循环使其达到排三组循环的效果

9--5--8--5

1--7--6

2--4--3

代码如下:

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

我们也可以只用两层循环实现,即分组排序的顺序改为

9--5,1--7,2--4,5--8,7--6,4--3,8--5.,实现代码如下:

cpp 复制代码
//Shell排序的双层循环的写法

void ShellSort(int* a, int n)
{
	int gap = 3;
	for (int i = 0; i < n - gap; i++)
	{
		int end = i;
		int tmp = a[end + gap];
		while (end >= 0)
		{
			if (tmp < a[end])
			{
				a[end + gap] = a[end];
				end -= gap;
			}
			else
			{
				break;
			}
		}
		a[end + gap] = tmp;
	}
}
总排序

gap一般取整个数组的数量除以三,为保证最后一次一定是1,我们将其设为gap = gap / 3 +1,这样最后就可以由一个插入排序对预排序后的数组进行总排序.并且我们每次预排序都会使数组更加有序,代码如下:

cpp 复制代码
void ShellSort(int* a, int n)
{
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1;
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
	}
}

希尔排序的速度

在release环境下,测试100,000个数据,其结果如下:

我们发现,希尔排序的速度是与堆排序是一个数量级的,而插入排序的速度也是比冒泡排序要快一个量级的.

测试1,000,000个数据

测试10,000,000个数据

堆排序的时间复杂度是O(),所以希尔排序的速度算是非常快的,有实践意义。

希尔排序的时间复杂度是 O().

相关推荐
泡海椒4 分钟前
JQuick-Excel 实战:用 STYLE 配置单元格与区域样式
开发语言·python·excel
java_nnnn6 分钟前
LeetCode刷题双指针(快乐数+盛最多水的容器)Java
算法·leetcode·职场和发展
Sarvartha8 小时前
final 关键字
java·开发语言
yi0119 小时前
LeetCode 219:存在重复元素 II——哈希表记录“最近一次出现的位置”
数据结构·人工智能·笔记·python·算法·leetcode·哈希表
程序员Sunday9 小时前
JavaScript 事件循环面试题,宏任务与微任务怎么执行|Sunday面试指南
开发语言·javascript·面试·校招·事件循环·程序员sunday
zhangzeyuaaa10 小时前
Ruby 多线程、GVL(GIL)与 Mutex 完全指南
开发语言·前端·ruby
谢亮_vipxieliang11 小时前
用 PHP 构建轻量级 REST API:从路由到鉴权的完整实践
开发语言·后端·php
Escalating_xu11 小时前
【C 语言】数据在内存中的存储:补码、大小端、整型陷阱与 IEEE 754 全解析
java·c语言·网络
思无邪6611 小时前
用 AI 做 JS 逆向:从抓包到复现的完整方法论
开发语言·javascript·人工智能
灯澜忆梦11 小时前
【面向对象编程C++】| 基础语法
java·c++·算法