【一看就懂的图解算法】希尔排序

希尔排序是基于插入排序的快速排序算法。对于大规模乱序数组插入排序很慢,因为他只会交换相邻的元素,因此元素只能一点一点的从数组的一端移动到另一端。如果最小的元素恰好在最末端,那么要挪到正确的位置需要移动n-1次。

希尔排序为了加快速度简单地改进了插入排序,交换不相邻的元素以对数组的局部进行排序,并最终用插入排序将局部有序的数组排序
——《算法》(第四版,2.1.6希尔排序)

根据上面这段,我的理解就是,希尔排序就是通过一种手段,将原本的数组状态1转换成为另一种状态2,最后使用插入排序完成排序,而状态2的时候使用插入排序比状态1的时候使用插入排序更快。

希尔排序的思想就是使得数组中间隔为h的元素都是有序的(称为h有序数组)。换句话说就是将一个数组划分成h个小数组,而小数组内部是有序的。

算法思想:
我们将需要排序的乱序数组划分成h组
不断缩小h,直到h=1
h=1,即我们学的插入排序,h不断缩小的过程就是我们将数组从状态1转化成为状态2的操作

算法图解:
【一看就懂的图解算法】希尔排序_第1张图片
小数组之间使用排序:
【一看就懂的图解算法】希尔排序_第2张图片
【一看就懂的图解算法】希尔排序_第3张图片
然后将h缩小
【一看就懂的图解算法】希尔排序_第4张图片
小数组之间再进行排序
【一看就懂的图解算法】希尔排序_第5张图片
【一看就懂的图解算法】希尔排序_第6张图片
然后h=1
使用插入排序

希尔排序完成!!!

那么我们最开始使用的h怎么去确定呢?

在《算法 第四版》对于希尔排序的算法代码为:

package sort;
/**
*@time 2020年4月25日:下午7:40:23
*@author Weirdo
*@version 1.0
**/
public class Shell {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		int[] arr= {5,1,2,4,3};
		sort(arr);
		for(int i:arr) {
			System.out.print(i+" ");
		}

	}
	
	public static void sort(int[] a){
		int N = a.length;
		int h=1;
		//这里就是对h最大能取多大进行判定
		while(h<N/3){
			h=3*h+1; // 1,4,13,40
		}
		while(h>=1){
			for(int i=h;i<N;i++){
			//less(a[j],a[j-h]) --> a[j]
				for(int j=i; j>=h && less(a[j],a[j-h]);j-=h){
					//交换
					exchang(a,j,j-h);
				}
			}
			h=h/3;
		}
	}

	private static boolean less(Integer i, Integer j) {
		// TODO Auto-generated method stub
		return i.compareTo(j)<0;
	}

	private static void exchang(int[] a, int j, int i) {
		// TODO Auto-generated method stub
		int temp=a[j];
		a[j]=a[i];
		a[i]=temp;
		
	}

	

}

和上面图解算法不同的地方在于,图解算法的h是成倍减小的,算法里的h是通过while()循环确定最大值,然后减少3倍,算法的思想都是一样的,通过划分数组,数组内部有序,缩小h

你可能感兴趣的:(数据结构与算法)