数据结构基础:P9.2-排序(一)--->希尔排序

本系列文章为浙江大学陈越、何钦铭数据结构学习笔记,前面的系列文章链接如下
数据结构基础:P1-基本概念
数据结构基础:P2.1-线性结构—>线性表
数据结构基础:P2.2-线性结构—>堆栈
数据结构基础:P2.3-线性结构—>队列
数据结构基础:P2.4-线性结构—>应用实例:多项式加法运算
数据结构基础:P2.5-线性结构—>应用实例:多项式乘法与加法运算-C实现
数据结构基础:P3.1-树(一)—>树与树的表示
数据结构基础:P3.2-树(一)—>二叉树及存储结构
数据结构基础:P3.3-树(一)—>二叉树的遍历
数据结构基础:P3.4-树(一)—>小白专场:树的同构-C语言实现
数据结构基础:P4.1-树(二)—>二叉搜索树
数据结构基础:P4.2-树(二)—>二叉平衡树
数据结构基础:P4.3-树(二)—>小白专场:是否同一棵二叉搜索树-C实现
数据结构基础:P4.4-树(二)—>线性结构之习题选讲:逆转链表
数据结构基础:P5.1-树(三)—>堆
数据结构基础:P5.2-树(三)—>哈夫曼树与哈夫曼编码
数据结构基础:P5.3-树(三)—>集合及运算
数据结构基础:P5.4-树(三)—>入门专场:堆中的路径
数据结构基础:P5.5-树(三)—>入门专场:File Transfer
数据结构基础:P6.1-图(一)—>什么是图
数据结构基础:P6.2-图(一)—>图的遍历
数据结构基础:P6.3-图(一)—>应用实例:拯救007
数据结构基础:P6.4-图(一)—>应用实例:六度空间
数据结构基础:P6.5-图(一)—>小白专场:如何建立图-C语言实现
数据结构基础:P7.1-图(二)—>树之习题选讲:Tree Traversals Again
数据结构基础:P7.2-图(二)—>树之习题选讲:Complete Binary Search Tree
数据结构基础:P7.3-图(二)—>树之习题选讲:Huffman Codes
数据结构基础:P7.4-图(二)—>最短路径问题
数据结构基础:P7.5-图(二)—>哈利·波特的考试
数据结构基础:P8.1-图(三)—>最小生成树问题
数据结构基础:P8.2-图(三)—>拓扑排序
数据结构基础:P8.3-图(三)—>图之习题选讲-旅游规划
数据结构基础:P9.1-排序(一)—>简单排序(冒泡、插入)

文章目录

  • 一、希尔排序(Shell Sort)
    • 1.1 希尔排序的例子
    • 1.2 希尔排序流程与代码实现
    • 1.3 希尔排序的复杂度
  • 二、C语言代码:希尔排序-用Sedgewick增量
  • 三、小测验


一、希尔排序(Shell Sort)

希尔排序是 Donald Shell 在1959年的时候提出来的,其基本思路就是:利用了插入排序的简单,同时他要克服插入排序每次只交换相邻两个元素这个缺点。

1.1 希尔排序的例子

例子:

我这里有个数组
在这里插入图片描述
Shell sort的第一步要先做一个5间隔的排序(这个序列每隔5个来选取元素构成子序列),这里得到子序列(81,35,41)
在这里插入图片描述
对这个子序列做插入排序,然后将其放在对应的位置
在这里插入图片描述
接着继续做一个5间隔的排序,这里得到序列(94,17,75)
在这里插入图片描述
对这个子序列做插入排序,然后将其放在对应的位置
在这里插入图片描述
接着继续做5间隔的排序,子序列为(11,95,15)
数据结构基础:P9.2-排序(一)--->希尔排序_第1张图片
接着继续做5间隔的排序,子序列为(96,28)
数据结构基础:P9.2-排序(一)--->希尔排序_第2张图片
接着继续做5间隔的排序,子序列为(12,58)
数据结构基础:P9.2-排序(一)--->希尔排序_第3张图片
此时调整间隔,在5间隔排序的结果基础上开始做3间隔排序。
开始做第一次3间隔排序
在这里插入图片描述
开始做第二次3间隔排序
在这里插入图片描述
开始做第三次3间隔排序
在这里插入图片描述
最后在3间隔排序的结果基础上做1间隔排序
在这里插入图片描述


1.2 希尔排序流程与代码实现

希尔排序的流程如下:

①定义增量序列 D M > D M − 1 > . . . > D 1 = 1 {D_M} > {D_{M - 1}} > ... > {D_1} = 1 DM>DM1>...>D1=1
上面我们是从5到3到1,一般而言初始的 D M = ⌊ N / 2 ⌋ , D k = ⌊ D k + 1 / 2 ⌋ {D_M} = \left\lfloor {N/2} \right\rfloor ,{D_k} = \left\lfloor {{D_{k + 1}}/2} \right\rfloor DM=N/2,Dk=Dk+1/2,然后每结束一轮让其除以2
②对每个 D k D_k Dk 进行 “ D k D_k Dk-间隔” 排序 ( k = M , M − 1 , … 1 ) \rm{(k = M, M-1, … 1 )} (k=M,M1,1)
进行 D 5 D_5 D5-间隔 排序
进行 D 3 D_3 D3-间隔 排序
进行 D 1 D_1 D1-间隔 排序
③注意:" D k D_k Dk-间隔" 有序的序列,在执行 “ D k − 1 D_{k-1} Dk1-间隔” 排序后,仍然是" D k D_k Dk-间隔" 有序的。
进行 D 3 D_3 D3-间隔 排序后的序列仍保持 D 5 D_5 D5-间隔 有序

希尔排序对应代码如下:

#include 

void Shell_sort(int A[], int N)
{
	int Tmp, i;
	for (int D = N / 2; D > 0; D /= 2) { /* 希尔增量序列 */
		for (int P = D; P < N; P++) { /* 插入排序 */
			Tmp = A[P];
			for (i = P; i >= D && A[i - D] > Tmp; i -= D)
				A[i] = A[i - D];
			A[i] = Tmp;
		}
	}
}

int main(void)
{
	int A[5] = {1, 5, -1, -4, 3};
	printf("希尔排序前:\n");
	for (int i = 0; i < 5; i++)
		printf("%d ", A[i]);
	Shell_sort(A, 5);
	printf("\n希尔排序后:\n");
	for(int i = 0; i < 5; i++)
		printf("%d ", A[i]);

	return 0;
}

运行,结果正确
数据结构基础:P9.2-排序(一)--->希尔排序_第4张图片


1.3 希尔排序的复杂度

但是一个很坏的消息是:最坏情况下,希尔排序的时间复杂度是 θ ( N 2 ) {\rm{\theta (}}{{\rm{N}}^{\rm{2}}}{\rm{)}} θ(N2)。注意的是,这里是 θ {\rm{\theta }} θ,代表即是上界也是下界,说明复杂度实打实的会达到 N 2 N^2 N2 这个数量级。而其他排序是 O O O,代表上界,也就是最坏情况下才会使这么大。

最坏情况

这里有以下数组,共16个元素,先做一次8-间隔排序,发现元素顺序没改变
在这里插入图片描述
在8-间隔排序结果基础上做4-间隔排序,发现顺序还是没变
在这里插入图片描述
在4-间隔排序结果基础上做2-间隔排序,发现顺序还是没变
在这里插入图片描述
最后还是靠1间隔排序才得到最终结果
在这里插入图片描述
原因分析:增量元素不互质(8是4的倍数,4是2的倍数),则小增量可能根本不起作用。


为了克服这个问题,有更多的学者提出了更多的增量序列。
数据结构基础:P9.2-排序(一)--->希尔排序_第5张图片
数据结构基础:P9.2-排序(一)--->希尔排序_第6张图片


二、C语言代码:希尔排序-用Sedgewick增量

整体代码如下

#include 
#include 
#include 

void ShellSort(int A[], int N)
{ /* 希尔排序 - 用Sedgewick增量序列 */
	int Si, D, P, i;
	int Tmp;
	/* 这里只列出一小部分增量 */
	int Sedgewick[] = { 929, 505, 209, 109, 41, 19, 5, 1, 0 };
	/* 初始的增量Sedgewick[Si]不能超过待排序列长度 */
	for (Si = 0; Sedgewick[Si] >= N; Si++); 

	for (D = Sedgewick[Si]; D > 0; D = Sedgewick[++Si]) {
		for (P = D; P < N; P++) { /* 插入排序*/
			Tmp = A[P];
			for (i = P; i >= D && A[i - D] > Tmp; i -= D)
				A[i] = A[i - D];
			A[i] = Tmp;
		}
	}
}

int main(void)
{
	int a;
	int A[30];
	//为数组A分配30个随机值
	srand((unsigned)time(NULL));
	for (int i = 0; i < 30; i++) {
		a = rand();
		A[i] = a;
	}	
	printf("希尔排序前:\n");
	for (int i = 0; i < 30; i++)
		printf("%d ", A[i]);
	ShellSort(A, 30);
	printf("\n希尔排序后:\n");
	for(int i = 0; i < 30; i++)
		printf("%d ", A[i]);

	return 0;
}

运行,结果正确
数据结构基础:P9.2-排序(一)--->希尔排序_第7张图片


三、小测验

希尔排序是稳定的 (错误)

你可能感兴趣的:(数据结构基础,数据结构,排序算法,算法,c算法,c语言)