Java算法9-高级排序

Java数据结构和算法(三)——冒泡、选择、插入排序算法中我们介绍了三种简单的排序算法,它们的时间复杂度大O表示法都是O(N2),如果数据量少,我们还能忍受,但是数据量大,那么这三种简单的排序所需要的时间则是我们所不能接受的。接着我们在讲解递归 的时候,介绍了归并排序,归并排序需要O(NlogN),这比简单排序要快了很多,但是归并排序有个缺点,它需要的空间是原始数组空间的两倍,当我们需要排序的数据占据了整个内存的一半以上的空间,那么是不能使用归并排序的。

本节课介绍几种高级的排序算法:希尔排序和快速排序。
  # 1 希尔排序

希尔排序是基于直接插入排序的,它在直接插入排序中增加了一个新特性,大大的提高了插入排序的执行效率。所以在讲解希尔排序之前,我们先回顾一下直接插入排序。

## ① 直接插入排序

直接插入排序基本思想是每一步将一个待排序的记录,插入到前面已经排好序的有序序列中去,直到插完所有元素为止。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wGMEgdap-1582363565437)(C:\课程文档\JDK源码解析\Java数据结构和算法\插入排序.png)]

实现代码为:

public class InsertSort {
   
	public static int[] sort(int[] array){
   
        int j;
        //从下标为1的元素开始选择合适的位置插入,因为下标为0的只有一个元素,默认是有序的
        for(int i = 1 ; i < array.length ; i++){
   
            int tmp = array[i];//记录要插入的数据
            j = i;
            while(j > 0 && tmp < array[j-1]){
   //从已经排序的序列最右边的开始比较,找到比其小的数
                array[j] = array[j-1];//向后挪动
                j--;
            }
            array[j] = tmp;//存在比其小的数,插入
            //第 i轮排序的结果为
            System.out.print("第"+(i)+"轮排序后的结果为:");
            display(array);
        }
        return array;
    }

}

我们可以分析一下这个直接插入排序,首先我们将需要插入的数放在一个临时变量中,这也是一个标记符,标记符左边的数是已经排好序的,标记符右边的数是需要排序的。接着将标记的数和左边排好序的数进行比较,假如比目标数大则将左边排好序的数向右边移动一位,直到找到比其小的位置进行插入。

这里就存在一个效率问题了,如果一个很小的数在很靠近右边的位置,比如上图右边待排序的数据 1 ,那么想让这个很小的数 1 插入到左边排好序的位置,那么左边排好序的数据项都必须向右移动一位,这个步骤就是将近执行了N次复制,虽然不是每个数据项都必须移动N个位置,但是每个数据项平均移动了N/2次,总共就是N2/2,因此插入排序的效率是O(N2)。

那么如果以某种方式不必一个一个移动中间所有的数据项,就能把较小的数据项移动到左边,那么这个算法的执行效率会有很大的改进。

② 希尔排序图解

希尔排序应运而生了,希尔排序通过加大插入排序中元素的间隔,并在这些有间隔的元素中进行插入排序,从而使数据项能够大跨度的移动。当这些数据项排过一趟序后,希尔排序算法减小数据项的间隔再进行排序,依次进行下去,最后间隔为1时,就是我们上面说的简单的直接插入排序。

下图显示了增量为4时对包含10个数组元素进行排序的第一个步骤,首先对下标为 0,4,8 的元素进行排序,完成排序之后,算法右移一步,对 1,5,9 号元素进行排序,依次类推,直到所有的元素完成一趟排序,也就是说间隔为4的元素都已经排列有序。
在这里插入图片描述
在这里插入图片描述
当我们完成4-增量排序之后,在进行普通的插入排序,即1-增量排序,会比前面直接执行简单插入排序要快很多。

③ 排序间隔选取

对于10个元素,我们选取4的间隔,那么100个数据,1000个数据,甚至更多的数据,我们应该怎么选取间隔呢?

希尔的原稿中 ,他建议间隔选为N/2,也就是每一趟都将排序分为两半,因此对于N=100的数组,逐渐减小的间隔序列为:50,25,12,6,3,1。这个方法的好处是不需要在开始排序前为找到初始序列的间隔而计算序列,只需要用2整除N。但是这已经被证明并不是最好的序列。

间隔序列中的数字互质是很重要的指标,也就是说,除了1,他们没有公约数。这个约束条件使得每一趟排序更有可能保持前一趟排序已经排好的结果,而希尔最初以N/2的间隔的低效性就是没有遵守这个准则。

所以一种希尔的变形方法是用2.2来整除每一个间隔,对于n=100的数组,会产生序列45,20,9,4,1。这比用2会整除会显著的改善排序效果。

还有一种很常用的间隔序列:knuth 间隔序列 3h+1

img

但是无论是什么间隔序列,最后必须满足一个条件,就是逐渐减小的间隔最后一定要等

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值