Java排序(四):希尔排序

版权声明:转载请注明原文地址。 https://blog.csdn.net/qq_39240270/article/details/87121121

希尔排序的实现思想

       希尔排序是插入排序的改进版,它与插入排序的不同之处在于,它会优先比较距离较远的元素。因此希尔排序又叫缩小增量排序。

  1. 选择一个增量序列,一般好的增量序列都有两个共同的特征:
    - 最后一个增量必须为1,保证最后一趟试一次普通的插入排序;
    - 应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况。
    本文中使用增量序列h = 3 * h + 1 来生成。h初值被赋予1,然后使用该公式生成序列1,4,13,40,121,364等等,当间隔大于数组大小的时候停止,使用序列的最大数组作为间隔开始希尔排序过程,然后每完成一次排序,用倒推公式h = h / 3来减小间隔,保证最后一次h = 1,完成最后一次插入排序。
  2. 按增量序列个数k,对序列进行k 趟排序; 3.每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。
  3. 仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

Java实现希尔排序

  1. 常规实现方法
	public static void shellSort(int[] a) {
		int h =1;//希尔排序是使间隔为h的元素有序
		int len = a.length;
		int temp,j;
		while(h < len / 3) {//生成最大h
			h = 3*h + 1;//用三倍作为希尔排序的间隔,是常用的值,加一是为了防止排序的都是三的倍数
		}
		while(h >= 1) {//while循环让h从大到小插入排序
			for(int i = h;i < len;i++) {//外层循环,从第h+1个元素开始,遍历后面的每一个元素,i为要比较的元素
				temp = a[i];//将要比较的元素存储在temp中。
				for(j = i-h;j >= 0 && a[j] > temp;j -= h) {//遍历把i每隔h位进行比较,确定要插入的位置
					a[j+h] = a[j];//当前面的元素比temp大时,将前面的值放在后面
				}
				a[j+h] = temp;//找到了要插入的位置,把要比较的值赋值给相应的元素,因为循环中j-h了,相当于a[i]。
			}
			h = h/3;//缩小插入间隔
		}
	}
  1. 每次比较,如果前面的更大都会交换,可以优化一下,直接把上面插入算法潜入内循环,比较的间隔由1改为h,比较的时候只移动插入位置,比较完只需要交换一次java实现。
	public static void shellSort(int[] a) {
		int h = 1; //希尔排序是使间隔为h的元素有序
		int insertIndex,insertElement;
		while(h < a.length/3) { //while循环,扩大h
			h = 3*h + 1; //这里用3倍作为希尔排序的间隔,是常用的值,加1是为了防止排序的都是3的倍数
		}
		while(h >= 1){ //while循环让h从大到小插入排序
			for(int i = h; i < a.length; i++){  //从第h+1个元素开始,对整个数组遍历,i为要比较元素的位置
				insertIndex = i - h; //要比较元素的位置,默认前面间隔h的位置
				insertElement = a[i]; //要比较的的元素,默认外层循环的最后一个元素
				while(insertIndex >= 0 && a[insertIndex] > insertElement){ //内层循环,只要新元素比要比较位置的元素小就继续
					a[insertIndex + h] = a[insertIndex]; //比要比较元素大的元素后移h位
					insertIndex -= h; //插入位置前移h位
				}
				a[insertIndex + h] = insertElement; //内层循环结束,把新元素放到插入位置后面
			}
			h = h/3; //更大间隔的插入完成,缩小插入间隔
		}
	}

总结

       希尔排序时间复杂度为O(NlogN),最好与最坏情况要根据具体的增量序列来判断,对于不同的增量序列有不同的复杂度。希尔排序的性能由于直接插入排序,因为在希尔排序开始时增量较大,分组较多,每组的记录数少,故各组内直接插入较快,后来随着增量逐渐减小,分组数逐渐减少,而各组的记录数逐渐增多,但是由于已经局部排过序了,所以已经接近有序状态,新的一趟排序过程也叫快。因此,希尔排序在效率上焦志杰插入排序有较大改进。
       希尔排序是不稳定,因为不同的间隔对应的数据是独自比较的,如果a=b,但是不在同一个间隔上,显示会出现前后颠倒的情况,所以希尔排序是不稳定。
       空间复杂度为O(1),不需要额外的存储空间。

猜你喜欢

转载自blog.csdn.net/qq_39240270/article/details/87121121