数据结构——希尔排序

一、前言

直接插入存在优化:可以通过对已排序好的序列,通过二分的方法,来找到待插入值的合适位置。

二分:

核心思路:每次砍掉一半范围,快速缩小答案区间,效率极高。

二、希尔排序(缩小增量排序)-》对直接插入排序的优化

1.核心:用到了缩小增量数组

2.直接插入排序的特点:

(1)数据也有序,整体排序效率越高。

(2)当n比较小的时候,n^2也不会很大-》时间复杂度 直接插入排序最理想的待排序序列是已经排序好的序列,所以时间复杂度就是O(n) 最糟糕的状态就是待排序序列是完全倒序,所以时间复杂度就是O(n^2)。

3.希尔排序的逻辑:

先将整个待排记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中记录"基本有序"时,在对全体记录进行一次直接插入排序。

跳着分组:

①第一次以增量为5为例,每个颜色对应的数据是一组。然后对这每一组单独进行直接插入排序。

不用排 10 21 50 本身有序。

按照刚刚方法完全排序完的序列:

②第二次以增量3为例,每个颜色对应的数据是一组。然后对这每一组单独进行直接插入排序。

以增量为3排序完的序列完全排序完的结果是

③第三次按照增量1排序,每个颜色对应的数据是一组。然后对这每一组单独进行直接插入排序。

以增量为1排序完的序列完全排序完的结果是

此时,最终只要按照增量1处理之后,会完全有序

3.缩小增量数组的取值好坏和希尔排序的时间复杂度直接相关,但又没有一个最优解。

但他有一些规则:

(1)取值从大到小

(2)取值尽量互素

(3)最后一个增量必须是1

4.希尔排序的特点:子序列的构成不是简单的"逐段分割",而是将相隔某个"增量"的记录组成一个子序列。

5.时间复杂度:

希尔排序的分析是个复杂的问题,因为它的时间是所取"增量"序列的函数,这涉及一些数学上尚未解决的难题。通俗的来说他的时间复杂度是动态变化的,到目前为止尚未有人求得一种最好的增量序列。增量序列可以有各种取法,但需注意:应使增量序列中的值没有除1之外的其他公因子也就是说他是素数,并且最后一个增量值必须等于1.

三、代码实现

方法一:以增量3为例

此时我们先处理红色组,再处理绿色组,最后处理蓝色组

此时有效值的处理顺序为:

红1->红2->红3->红4->红5->绿1->绿2->绿3->绿4->绿5->蓝1->蓝2->蓝3->蓝4->蓝5

时间复杂度是O(n^3).

方法二:

不再处理完一个组,再处理下一个组,而是每一个组一次只处理一个值,然后轮换,直到所有的值处理完毕。

全部此时有效值的处理顺序为:

红2->绿2->蓝2->红3->绿3->蓝3->红4->绿4->蓝4->红5->绿5->蓝5

代码实现:

cs 复制代码
void Shell(int arr[], int len, int gap_val) {
	//此时增量为5;
	//需要将每一个执行插入排序
	for (int i = gap_val;i < len;i++) {//此时i控制的需要往前插入的待排序值 gap_val前面的值都是每一组的第一个元素,第一个元素不用排
		int tmp = arr[i];
		int j = i - gap_val;
		for (;j >= 0;j -= gap_val) {
			if (arr[j] > tmp) {
				arr[j + gap_val] = arr[j];
			}
			else {
				break;//遇到了不大于我的值,停下来把值放回去
			}
		}
		//越界了,停下来,把值放回去
		arr[j + gap_val] = tmp;
	}
}
void Shell_Sort(int arr[], int len) {
	int Gap[] = { 5,3,1 };
	int len_Gap = sizeof(Gap) / sizeof(Gap[0]);
	for (int i = 0;i < len_Gap;i++) {//趟数
		Shell(arr,len,Gap[i]);
	}
}
相关推荐
小雪崩2 小时前
嵌入式学习 day25:哈希表及排序与查找
linux·c语言·数据结构·学习·排序算法
_Narcissus_4 小时前
动态规划初探(含完整代码实现)
c语言·数据结构·c++·算法·动态规划·背包问题·最短路径
_Narcissus_6 小时前
枚举和模拟算法笔记
c语言·数据结构·c++·笔记·算法·模拟·枚举
冻柠檬飞冰走茶6 小时前
《数据结构实验指导-C++语言版》 在顺序表 list 中查找元素 x
开发语言·数据结构·c++·算法·list
Brilliantwxx6 小时前
【C++】 高阶数据结构图(1)并查集
开发语言·数据结构·c++
Fa_Mian_Tuan7 小时前
最小生成树之Kruskal算法(超详细原理+完整可运行C语言代码)
c语言·开发语言·数据结构·笔记·算法·图论
冻柠檬飞冰走茶7 小时前
《数据结构实验指导-C++语言版》 返回单链表 list 中第 i 个元素值
开发语言·数据结构·c++·算法·list
LuminousCPP9 小时前
栈和队列专题(四):LeetCode 232. 用栈实现队列|双栈分工 + 按需迁移 + 摊还 O(1)
c语言·数据结构·笔记·算法·leetcode
纪念 2299 小时前
二叉树排序讲解(一)
数据结构
tudousisi2229 小时前
01背包8.21
数据结构·算法