希尔排序

205 阅读2分钟

本质上也是插入排序:也称缩小量排序,针对arr={2,3,4,5,6,1}这种需要插入的数是较小数时,后移的次数明显增多,效率低。

基本思想:把元素按下标的一定增量分组,对每组数据直接使用插入排序算法排序,随着增量的逐渐减小,每组包含的元素的个数越来越多,当增量为1时,终止算法。

原始数组:8,9,1,7,2,3,5,4,6,0

初始增量:gap = length/2 = 5;

分组为:[8,3],[9,5],[1,4],[7,6],[2,0],但是原始的数据位置不变,组内数据位置变化为[3,8],[5,9],[1,4],[6,7],[0,2]。

第一次希尔排序为:3,5,1,6,0,8,9,4,7,2

第一次缩小增量:gap = length/2/2 = 2(向下取整);

分组为:[3,1,0,9,7]和[5,6,8,4,2],组内数据变化为[0,1,3,7,9]和[2,4,5,6,8]。

第二次希尔排序为:0,2,1,4,3,5,7,6,9,8

第二次缩小增量:gap = length/2/2/2 = 1

排序后得:0,1,2,3,4,5,6,7,8,9

希尔排序中,对有序序列在插入时采用交换法和移动法。

交换法:
public static void shellSort(int[] arr) 
{
	int temp = 0;
    for (int gap = arr.length/2; gap > 0; gap/=2)
    {
    	for (int i = gap; i < arr.length; i++) 
        {
        	//遍历各组中的所有元素,共gap组,步长为gap,每组有arr.length/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;
                }
            }
        }
    } 
}
 //移位法
public static void shellSort2(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;
            }
        }
    }
}