【排序】希尔排序(C语言实现)

文章目录

  • 前言
  • [1. 希尔排序的思想](#1. 希尔排序的思想)
  • [2. 希尔排序的一些小优化](#2. 希尔排序的一些小优化)

前言


本章将详细介绍希尔排序的思想及实现,由于希尔排序是在插入排序 的思想上进行升华,所以如果不知道插入排序或者不熟悉的可以先看看这篇文章:《简单排序》中的直接插入排序。

1. 希尔排序的思想

希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成gap个组,所有距离为gap的数据分在同一组内,并对每一组内的记录进行排序。当gap组都排完以后,我们将gap缩小,重复上述分组和排序的工作。当gap = 1时(此时就是直接插入排序),所有记录在统一组内排好序。

具体步骤如下图:



我们可以按照上面的思路,来用代码进行模拟实现:

cpp 复制代码
void ShellSort(int* a, int n)
{
	int gap = n;
	while (gap > 0)
	{
		// 每次gap/3 + 1,当gap为1时,就是选择排序
		gap /= 2;
		int count = 0;
		// 调整几组取决于gap为多大
		while (count < gap)
		{
			// 每组调整的步骤
			for (int i = 0;i < n - gap;i += gap)
			{
				int tmp = a[i + gap]; // 定义一个临时值,用来保存每次要插入的数
				int j = 0; //控制循环的变量
				for (j = i;j >= 0;j -= gap)
				{
					// 从后面开始比,如果tmp比后面的数小,就将后面的数往后移gap
					if (a[j] > tmp)
						a[j + gap] = a[j];
					else// 如果tmp比后面的数要大,就直接退出,因为我们是从第一个数开始这样操作的,前面能够保证是有序的
						break;
				}
				a[j + gap] = tmp;
			}

			count++;
		}
	}
}

希尔排序的特性总结:

  1. 希尔排序是对直接插入排序的优化。
  2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。
  3. 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的希尔排序的时间复杂度都不固定:
    《数据结构(C语言版)》--- 严蔚敏
    《数据结构-用面相对象方法与C++描述》--- 殷人昆
  4. 稳定性:不稳定

2. 希尔排序的一些小优化

我们上面那个实现的方式是取gap=[n / 2],gap=[gap / 2],直到gap=1,但我们看到 《数据结构-用面相对象方法与C++描述》--- 殷人昆 中提到Hnuth取gap的方法,可以有一定程度上的提高我们的速度,具体是怎么提高的呢,因为这块涉及到很难的数学知识,目前还没人能够给出完整的数学分析,所以我们也不必去纠结,只要记住他们这些大佬经过多次实验提出的结论就可以了。

这里我打算进行两个优化:

  1. 就是gap的取值
  2. 我们上面每次排序是一组一组的排序,其实我们可以一次性全部排序完(这里效率上没有提升,只是代码量减少了)

具体代码如下:

cpp 复制代码
void ShellSort(int* a, int n)
{
	int gap = n;
	while (gap > 1) // gap最小等于1,所以这里的循环条件需要控制一下
	{
		// 每次gap/3 + 1,+1的目的是为了保证gap一定会等于1
		gap = gap / 3 + 1;
		// 我们将gap组一起调整
		for (int i = 0;i < n - gap;++i)
		{
			int tmp = a[i + gap];// 定义一个临时值,用来保存每次要插入的数
			int j = 0; // 控制循环的变量
			for (j = i;j >= 0;j -= gap)
			{
				if (a[j] > tmp)
				{
					a[j + gap] = a[j];
				}
				else
					break;
			}
			a[j + gap] = tmp;
		}
	}
}
相关推荐
PAK向日葵5 小时前
【算法导论】PDD 0817笔试题题解
算法·面试
地平线开发者7 小时前
ReID/OSNet 算法模型量化转换实践
算法·自动驾驶
地平线开发者7 小时前
开发者说|EmbodiedGen:为具身智能打造可交互3D世界生成引擎
算法·自动驾驶
星星火柴9369 小时前
关于“双指针法“的总结
数据结构·c++·笔记·学习·算法
艾莉丝努力练剑9 小时前
【洛谷刷题】用C语言和C++做一些入门题,练习洛谷IDE模式:分支机构(一)
c语言·开发语言·数据结构·c++·学习·算法
C++、Java和Python的菜鸟11 小时前
第六章 统计初步
算法·机器学习·概率论
Cx330❀11 小时前
【数据结构初阶】--排序(五):计数排序,排序算法复杂度对比和稳定性分析
c语言·数据结构·经验分享·笔记·算法·排序算法
散11211 小时前
01数据结构-Prim算法
数据结构·算法·图论
起个昵称吧11 小时前
线程相关编程、线程间通信、互斥锁
linux·算法
..过云雨12 小时前
01.【数据结构-C语言】数据结构概念&算法效率(时间复杂度和空间复杂度)
c语言·数据结构·笔记·学习