排序:希尔排序

希尔排序

直接插入排序

  在正式开始学习希尔排序之前,我们可以先学习他的前身:直接插入排序
直接插入排序算法的具体步骤:
1.在插入第 i i i个数时,前 i − 1 i-1 i1个数已经排好序
2.将第 i i i个数与前 i − 1 i-1 i1个数进行比较,从而找到插入位置并插入第 i i i个数
3.将插入位置及其后的数依次向后移动
直接插入排序代码(升序排序)

/*将数组data[0]~data[n-1]中的n个整数升序排列*/
void InsertSort(int data[], n) {
	for(int i = 1; i < n; i++) {
		if(data[i-1] > data[i]) {
			int tmp = data[i];
			data[i] = data[i-1];
			int j;
			for(j = i-1; j >= 0 && data[j] > tmp; j--)
				data[j+1] = data[j];
			data[j+1] = tmp;
		}
	}
} 

手动模拟直接插入排序过程
请添加图片描述

  直接插入排序是一种稳定的排序方法,其时间复杂度为 O ( n 2 ) O(n^2) O(n2),在排序过程中仅需要一个元素的辅助空间,空间复杂度为 O ( 1 ) O(1) O(1)

希尔排序

  希尔排序又称为“缩小增量排序”,他是对直接插入排序方法的改进。
希尔排序算法的具体步骤:
1.构造一个步长序列为 d e l t a 1 , d e l t a 2 , . . . , d e l t a k delta1, delta2, ..., deltak delta1,delta2,...,deltak,其中 d e l t a 1 = n / 2 delta1 = n/2 delta1=n/2,后面的每个delta是前一个的 1 / 2 1/2 1/2 d e l t a k = 1 deltak = 1 deltak=1
2.根据步长序列,进行 k k k趟排序
3.对第 i i i趟排序,根据对应的步长 d e l t a delta delta,将等步长位置元素分组,对同一组内元素在原位置上进行直接插入排序
希尔排序代码(升序排序)

void ShellSort(int data[], int n) {
	int k = n, dk;
	int *delta = (int *)malloc(sizeof(int) * (n/2));
	for(int i = 0; k >= 1; k /= 2)
		delta[i++] = k;
	for(int i = 0; (dk = delta[i]) > 0; i++) {
		for(k = delta[i]; k < n; k++) {
			if(data[k-dk] > data[k]) {
				int tmp = data[k]; 	//备份待插入元素,空出一个元素位置
				int j;
				for(j = k-dk; j >= 0 && data[j] > tmp; j -= dk)
					data[j+dk] = data[j];	//寻找插入位置的同时元素后移动
				data[j+dk] = tmp;	//找到插入位置,插入元素,取下一个增量值
 			}
 		}
 	}
}	

手动模拟希尔排序过程
请添加图片描述
  希尔排序是一种不稳定的排序方法,时间复杂度约为 O ( n 1.3 ) O(n^{1.3}) O(n1.3),排序过程中仅需要一个元素的辅助空间用于数组元素值的交换,空间复杂度为 O ( 1 ) O(1) O(1)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值