算法笔记:排序算法-希尔排序

排序算法-希尔排序

方法

希尔排序是基于插入排序实现的,之前的博客分析过,插入排序在数组基本有序的时候,也就是倒置元素数量尽可能少的时候效率很高。

希尔排序的思想就是,先在整个数组中划分出规模比较小的数组,将这些小的数组先进行插入排序,将小的数组变得有序。在将小的数组变得有序之后,整个数组的倒置元素数量变少了,此时再进行插入排序的效率也变高了。因此我需要先分成若干个规模小一点的数组,进行插入排序,之后再划分成若干个大一点规模的数组进行排序…直到划分成最终一整个数组,这样我们最终就能得到一个有序的数组了。

具体步骤:
假设数组 arr 有n个无序元素。
设定一个划分间隔 h

首次划分:
将 arr[0] arr[h] arr[2h] … 划为一个数组
将 arr[1] arr[h+1] arr[2h+1] … 划为一个数组

将 arr[h-1] arr[2h-1] arr[3h-1] … 划为一个数组

将这些数组划分好了之后,对其插入排序,因为 h 一开始会设定成一个较大的数,所以这些数组规模较小,用插入排序可以很快的完成排序。此时数组已经减少了很多倒置元素。
完成首次划分之后,将 h 变小再次进行划分排序,不断地进行这个循环。每一次划分排序都会减小数组的无序性,也就是说倒置元素会越来越少,直到 h 变为 1 的时候,数组只能划分成一整个原数组。此时再对基本有序的原数组进行排序,效率就非常高了。

实现

@Override
	public void sort(int[] arr) {
		int length = arr.length;
		int h = 1;
		while (h < length/3)
			h = 3*h + 1;
		
		while (h >= 1) {
			insertsort(arr, h);
			h = h/3;
		}
	}
	
	private void insertsort(int[] arr, int h) {
		for (int i = 0; i < arr.length; i += h) {
			int n = arr[i];
			int loc = i;
			for (int j = i; j > 0; j -= h) {
				if (n >= arr[j-h]) break;
				arr[j] = arr[j-h];
				loc = j-h;
			}
			arr[loc] = n;
			
		}
	}

复杂度分析

因为是基于插入排序的算法,因此在数组倒置元素越少的情况下,该算法效率也会越高。

时间复杂度

水平不足分析出时间复杂度,就直接放别人的结果了:O(n^(1.3—2))

空间复杂度

在原数组的空间上进行交换,所以空间复杂度为 O(1)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值