插入排序的理解以及希尔排序的实现

1 插入排序的实现 

算法思路:将数组的第一个数认为是有序数组,从数组的第二个元素开始将后面的元素依次插入到有序数组的合适位置。
如下图所示:

                                                                  

2 代码实现

public static void main(String[] args) {
		int[] arr = { 1, 5, 3, 7, 8, 6, 2, 4, 11, 12, 13, 14, 15 };
		for (int i = 1; i < arr.length; i++) {// begin=1表示 默认数组第一个元素是有序的
			int temp = arr[i];// 取出下一个元素,在已经排序的元素序列中从后向前扫描
			int j = i;
			// 用取下的元素依次和索引为 j-1 元素进行比较,因为要比较的元素索引为j-1 所以要保证j>0即不能越界
			while (j > 0 && temp < arr[j - 1]) {// 注意j>0放到前面
				arr[j] = arr[j - 1];// 如果temp小于当前比较的元素,那么就把当前的比较的元素arr[j-1]向后移动一位
				j--;// 比较下一个元素的索引时 j需要减1
			}
			arr[j] = temp;// 把temp查到找到的位置 注意这里是j 可以简化直接考虑j=0的情况
		}
		System.out.println(Arrays.toString(arr));
	}

        

3 希尔排序 

希尔排序,也称递减增量排序算法,希尔排序是先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。

算法思路:将待排序数组按照步长gap进行分组,然后将每组的元素利用直接插入排序的方法进行排序;每次再将gap折半减小,循环上述操作;当gap=1时,利用直接插入,完成排序。可以看到步长的选择是希尔排序的重要部分。只要最终步长为1任何步长序列都可以工作。一般来说最简单的步长取值是初次取数组长度的一半为增量,之后每次再减半,直到增量为1。

4 代码实现

代码思路

  1. 先求解数组分组时用的步长,以数组[9,8,7,6,5,4,3,2,1]为例,计算其步长为[4,2,1],数组的长度每次除2,当然还有其他的计算方法,这里就以最简单的这种方式为例
  2. 按照步长进行分组,并进行插入排序,
    第一次以步长为4进行分组  分组为  [9,5,1]     [8,4]    [7,3]    [6,2] ,对分好的组按插入排序进行排序
    以第一组[9,5,1]   为例进行插入排序,实际排序数组为  [9,  _,  _,  _,  5,   _,   _,  _, 1] 
                                                                          排序结果   [1,  _,  _,  _,  5,   _,   _,  _, 9] 
    按照步长为5进行排序完成后数组结果为[1,4,3,2,5,8,7,6,9]
  3. 再按照步长为2 和 1分别进行排序
  4. 当按照步长为1排序时 实际就是直接插入排序,只不过这是的数组的元素大部分已经是有序的了。
public static void mysort(){
    int[] arr = { 19, 28, 7, 36, 15, 4, 33, 2, 11 };// 测试用例
    List<Integer> stepSquence = new LinkedList<>();
	int size = arr.length;
	while ((size >>= 1) > 0) {
	   stepSquence.add(size);// 计算分组的步长
	}
	for (int step : stepSquence) {// 依次按照步长进行分组排序
	   // 当按照步长stepNum分割数组,得到stepNum个数组,
	   // 例如步长为2 分割得到的数组为[9,7,5,3,1] [8,6,4,2]
	    for (int col = 0; col < step; col++) {// col表示第几个分组
		// 下面的代码是按照步长为step进行插入排序,参考直接插入排序的实现
		  for (int begin = col + step; begin < arr.length; begin += step) {// col+step  表示当前排序分组的第二个元素索引,默认第一个元素有序
			int temp = arr[begin];// 取出下一个元素,在已经排序的元素序列中从后向前扫描
			int cur = begin;
			while (cur > col && temp < arr[cur - step] ) {// 注意cur>col条件 表示不能越界
				arr[cur] = arr[cur - step];// 向后移动step步长
				cur-=step;
			}
			arr[cur] = temp;// temp插入到合适的位置
		  }
		}
	}
	System.out.println(Arrays.toString(arr));
}

4 希尔排序的步长

5 希尔排序的时间复杂度,希尔排序的时间复杂度与排序的步长取值有关,当按照上图所示的步长进行排序时最坏情况为 n(4/3)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值