插入排序——希尔排序

插入排序思想:

    插入排序分有序区、无序区,最开始有序区没有元素,无序区为整个待排序区。排序时,每一趟排序将一个无序区的元素插入到有序区适当的位置,直到无序区的元素为空。

    插入排序根据具体的排序算法不同,又分为直接插入排序、折半插入排序、希尔排序。

希尔排序:

        又称缩小增量排序。实际上是分组插入排序

        比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换。D.L.shell于1959年在以他名字命名的排序算法中实现了这一思想。算法先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。

        本质上讲,希尔排序算法是直接插入排序算法的一种改进,减少了其复制的次数,速度要快很多。 原因是,当d值很大时数据项每一趟排序需要移动的个数很少,但数据项的距离很长。当d值减小时每一趟需要移动的数据增多,此时已经接近于它们排序后的最终位置。 正是这两种情况的结合才使希尔排序效率比插入排序高很多。Shell算法的性能与所选取的分组长度序列有很大关系。只对特定的待排序记录序列,可以准确地估算关键词的比较次数和对象移动次数。想要弄清关键词比较次数和记录移动次数与增量选择之间的关系,并给出完整的数学分析,至今仍然是数学难题。

        希尔排序按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。

一般的初次取序列的一半为增量,以后每次减半,直到增量为1。

希尔排序java实现:


/**
	 * 初始分组的距离d为排序数据规模的一半n/2,以后再缩小一半。
	 * @param array
	 */
	static void shellSort(int[] array) {
		int n= array.length;
		int j, d = n/2;
		int tmp;
		while(d>0) {//分组的距离d变化一次,缩小一半
			for(int i=d; i<n; i++) {
				/**
				 * 这个循环有两个2个意思:
				 * 当i为d到2d-1,2d到3d-1,依次类推,直到n,
				 * 1、在同一段内每一次循环表示不同分组的同一趟排序,每循环一次一个分组排序一趟,一个分组有序区增加一个元素
				 * 2、不同的段代表分组的不同排序趟。
				 * 即是:2d到2d-1中的循环为所有分组的第一趟,2d到3d-1中的循环为所有分组的第二趟。。。。
				 */
				tmp = array[i];
				j = i - d;
				while(j>=0 && tmp < array[j]) {//找到
					array[j+d] = array[j];
					j = j - d;
				}
				array[j+d] = tmp;
			}
			d = d / 2;
		}
	}

空间复杂度为:O(1)

希尔排序是不稳定排序,平均时间复杂度为(怎么算出来的,我不太清楚,没推算过)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值