数据结构与算法学习笔记——希尔排序

希尔排序 —— 插入排序的升级版

1. 希尔排序介绍

希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序。它的时间复杂度为O(n^(1.3—2))

2. 希尔排序法基本思想

希尔排序是把数据按下标的一定增量分组,对每组使用插入排序;随着增量逐渐减少,当增量减至1时,整个数据恰被分成一组,算法便终止。

3. 希尔排序法的示意图

转载于《老韩图解Java数据结构与算法》

希尔排序法的示意图

4. 代码逐步实现

// 要排序的数据
int[] arr = { 8, 9, 1, 7, 2, 3, 5, 4, 6, 0 };

4.1 交换法

// 希尔排序的第1轮排序
// 因为第1轮排序,是将10个数据分成了5组
for (int i = 5; i < arr.length; i++) {
	// 遍历各组中所有的元素(共5组,每组有2个元素), 步长5
	for (int j = i - 5; j >= 0; j -= 5) {
		// 如果当前元素大于加上步长后的那个元素,说明交换
		if (arr[j] > arr[j + 5]) {
			temp = arr[j];
			arr[j] = arr[j + 5];
			arr[j + 5] = temp;
		}
	}
}
// 希尔排序的第2轮排序
// 因为第2轮排序,是将10个数据分成了 5/2 = 2组
	for (int i = 2; i < arr.length; i++) {
		// 遍历各组中所有的元素(共2组,每组有5个元素), 步长2
		for (int j = i - 2; j >= 0; j -= 2) {
			// 如果当前元素大于加上步长后的那个元素,说明交换
			if (arr[j] > arr[j + 2]) {
				temp = arr[j];
				arr[j] = arr[j + 2];
				arr[j + 2] = temp;
			}
		}
	}
// 希尔排序的第3轮排序
// 因为第3轮排序,是将10个数据分成了 2/2 = 1组
for (int i = 1; i < arr.length; i++) {
	// 遍历各组中所有的元素
	for (int j = i - 1; j >= 0; j -= 1) {
		// 如果当前元素大于加上步长后的那个元素,说明交换
		if (arr[j] > arr[j + 1]) {
			temp = arr[j];
			arr[j] = arr[j + 1];
			arr[j + 1] = temp;
		}
	}
}

综上步骤

int temp = 0;
int count = 0;
// 根据前面的逐步分析,使用循环处理
for (int gap = arr.length / 2; gap > 0; gap /= 2) {
	for (int i = gap; i < arr.length; i++) {
		// 遍历各组中所有的元素(共gap组), 步长gap
		for (int j = i - gap; j >= 0; j -= gap) {
			// 如果当前元素大于加上步长后的那个元素,说明交换
			if (arr[j] > arr[j + gap]) {
				temp = arr[j];
				arr[j] = arr[j + gap];
				arr[j + gap] = temp;
			}
		}
	}
}

上面采用交换的方式实现的排序花费时间大,不推荐使用,按照交换的思路继续,替换成插入法

4.2 插入法

/**
 * 对交换式的希尔排序进行优化
 * @param arr
 */
public static void shellSort(int[] arr) {
   // 增量gap, 并逐步的缩小增量
    for (int gap = arr.length / 2; gap > 0; gap /= 2) {
        // 从第gap个元素, 逐个对其所在的组进行直接插入排序
        for (int i = gap; i < arr.length; i++) {
            int j = i;
            int temp = arr[j];
            if (arr[j] < arr[j - gap]) {
                while (j - gap >= 0 && temp < arr[j - gap]) {
                    // 移动
                    arr[j] = arr[j - gap];
                    j -= gap;
                }
                // 当退出while后, 就给temp找到插入的位置
                arr[j] = temp;
            }
        }
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值