算法--希尔排序

对于大规模乱序数组插入排序很慢,因为它只会交换相邻的元素,因此元素只能一点一点地从数组的一端移动到另一端。例如,如果主键最小的元素正好在数组的尽头,要将它挪到正确的位置就需要 N-1 次移动。希尔排序为了加快速度简单地改进了插入排序,交换不相邻的元素以对数组的局部进行排序,并最终用插入排序将局部有序的数组排序。

基本思想:
先取一个小于数组长度n的整数h作为第一个增量,把数组的全部元素分组。所有距离为h的倍数的元素放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量h(小于第一个增量h)重复上述的分组和排序,直至所取的增量h=1,即所有元素放在同一组中进行直接插入排序为止。

该方法实质上是基于插入算法的一种分组插入方法。

比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换。

D.L.shell于1959年在以他名字命名的排序算法中实现了这一思想。算法先将要排序的一组数按某个增量h分成若干组,每组中元素的下标相差h.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。

算法的性能与h的选择有关,但是h的选择仍然是数学的前沿研究问题,没有定论,我们只能根据我们的经验和需要来选取适合的h。

稳定性:
由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。

复杂度:
希尔排序的时间复杂度与增量序列的选取有关,例如希尔增量时间复杂度为O(n²),而Hibbard增量的希尔排序的时间复杂度为O(n的3/2次方),希尔排序时间复杂度的下界是n*log2n。
空间复杂度为O(1)。

代码实现:

public class Test {
	public static void sort(int[] numbers) {
		int l = numbers.length;
		int h = 1;
		int count = 0;
		while (h < l/3) h = h*3+1;//确定有序子数组的个数h
		while (h >= 1) {
			count++;
			for (int i = h;i < l;i++) {
				for (int j = i;j >= h;j -= h) {
					if ((numbers[j] < numbers[j-h])){
						int temp = numbers[j];
						numbers[j] = numbers[j-h];
						numbers[j-h] = temp;
					}
				}
			}
			System.out.println("第" + count + "趟排序");
			System.out.println(Arrays.toString(numbers));
			h = h/3;//重新选取h
		}
	}
	
	public static void main(String[] args) {
		int[] numbers = {1,5,9,8,7,2,3,5,4,0};
		System.out.println("排序前:");
		System.out.println(Arrays.toString(numbers));
		sort(numbers);
	}
}

运行结果:

这里写图片描述

### 希尔排序算法详解 #### 算法概述 希尔排序(Shell Sort),亦称为递减增量排序算法,是对插入排序的一种优化版本[^1]。该算法由Donald Shell于1959年提出,并在论文“A high-speed sorting procedure”中对其进行了详细的阐述[^3]。 #### 工作原理 希尔排序通过比较相隔一定间隔的元素来工作,这些间隔逐渐减少直到变为1。当间隔为1时,希尔排序即成为普通的插入排序。这种策略使得远距离的数据可以更快地移动到接近其最终位置的地方,从而提高了整体性能[^4]。 #### 时间复杂度分析 尽管具体的渐近时间复杂度取决于所使用的间隔序列,但在最坏情况下,希尔排序的时间复杂度通常优于简单的插入排序。对于某些特定的选择间隔序列,平均情况下的表现甚至能够达到接近\( O(n \log n) \)。 #### 实现细节 以下是使用Python编写的希尔排序的具体实现: ```python def shell_sort(arr): n = len(arr) gap = n // 2 while gap > 0: for i in range(gap, n): temp = arr[i] j = i while j >= gap and arr[j - gap] > temp: arr[j] = arr[j - gap] j -= gap arr[j] = temp gap //= 2 if __name__ == "__main__": test_array = [64, 34, 25, 12, 22, 11, 90] print("原始数组:", test_array) shell_sort(test_array) print("排序后的数组:", test_array) ``` 这段代码展示了如何利用逐步缩小的间隔来进行多次部分有序化的操作,最后完成整个列表的完全排序过程[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值