排序优化

Collections.sort()方法底层使用Arrays.sort()实现的!

而Arrays中对于集合类的sort()方法主要采用TimSort算法(优化的归并算法)(对应数组的算法主要采用DualPivotQuicksort.sort()(优化的快速排序算法)), 大致思路是这样的:

  1. 元素个数 < 32, 采用二分查找插入排序(Binary Sort)
  2. 元素个数 >= 32, 采用归并排序,归并的核心是分区(Run)
  3. 找连续升或降的序列作为分区,分区最终被调整为升序后压入栈
  4. 如果分区长度太小,通过二分插入排序扩充分区长度到分区最小阙值
  5. 每次压入栈,都要检查栈内已存在的分区是否满足合并条件,满足则进行合并
  6. 最终栈内的分区被全部合并,得到一个排序好的数组

Timsort的合并算法非常巧妙:

  1. 找出左分区最后一个元素(最大)及在右分区的位置
  2. 找出右分区第一个元素(最小)及在左分区的位置
  3. 仅对这两个位置之间的元素进行合并,之外的元素本身就是有序的

所有的排序(二叉树也是)的比较都是基于compareTo()实现的!!!
所以要排序一个自定义的对象,那么:
4. 该类一定要实现Comparable< T >接口实现compareTo()方法;
5. 或者构造一个比较器,实现Comparator< T >的compare()方法!!!


在这里插入图片描述

如何优化快速排序?

如果数据原来就是有序的或者接近有序的,每次分区点都选择最后一个数据,那快速排序算法就会变得非常糟糕,时间复杂度就会退化为 O(n2)。实际上,这种 O(n2) 时间复杂度出现的主要原因还是因为我们分区点选得不够合理。

1. 三数取中法(主要)

我们从区间的首、尾、中间,分别取出一个数,然后对比大小,取这 3 个数的中间值作为分区点。这样每间隔某个固定的长度,取数据出来比较,将中间值作为分区点的分区算法,肯定要比单纯取某一个数据更好。但是,如果要排序的数组比较大,那“三数取中”可能就不够了,可能要“五数取中”或者“十数取中”。

2. 随机法

随机法就是每次从要排序的区间中,随机选择一个元素作为分区点。这种方法并不能保证每次分区点都选的比较好,但是从概率的角度来看,也不大可能会出现每次分区点都选得很差的情况,所以平均情况下,这样选的分区点是比较好的。时间复杂度退化为最糟糕的 O(n2) 的情况,出现的可能性不大。

递归优化

1.限制递归深度

一旦递归过深,超过了我们事先设定的阈值,就停止递归。

2. 通过在堆上模拟实现一个函数调用栈,手动模拟递归压栈、出栈的过程,这样就没有了系统栈大小的限制。(主要)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值