博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
排序优化——如何实现一个通用的、高性能的排序函数
阅读量:5744 次
发布时间:2019-06-18

本文共 908 字,大约阅读时间需要 3 分钟。

几乎所有的编程语言都会提供排序函数,比如 C 语言的 qsort(), C++ STL 中的 sort(),这些排序函数是如何实现的呢?

1. 如何选择合适的排序算法?

如果要实现一个通用的高效率的排序函数,我们应该选择那种排序算法呢?

  • 各种排序算法的特点如下所示。

  • 线性排序算法的时间复杂度比较低,适用场景特殊,因此不适合作为通用的排序函数。

  • 小规模数据可以选择时间复杂度为 O(n^2) 的算法,大规模数据选择时间复杂度为 O(nlogn) 的算法则会更加高效。为了兼顾任意规模的数据,一般会首选复杂度为 O(nlogn) 的算法来实现排序函数。

  • 归并排序虽然最好情况、最坏情况和平均情况下时间复杂度都可以做到 O(nlogn),但它不是原地排序算法,空间复杂度为 O(n),排序的时候需要的额外空间和源数据一般大,空间消耗过高。


2. 如何优化快速排序?

快速排序最坏情况下时间复杂度退化为 O(n^2) ,我们怎样来避免这种情况的发生呢?

  • 实际上,这种 O(n^2) 复杂度出现的主要原因还是分区点选取得不合理

  • 理想的分区点应该是,被分区点分开的两个区间,数据的数量差不多。

2.1. 分区点优化问题

  • 三数取中法。从待排序数据首、尾、中分别取出一个数,然后对比大小,以这三个数的中间值作为分区点。

  • 如果排序数据比较多,可能要“五数取中”或者“十数取中”。

  • 随机法。每次从要排序的区间随机选择一个元素作为分区点,这种情况下,就可以避免每次分区点都选得非常糟糕。

2.2. 堆栈溢出问题

快速排序是利用递归来实现的,当递归的的深度过深时,就会导致堆栈溢出。

  • 限制递归深度。当递归次数超过我们设定的阈值时,就停止递归。
  • 在堆上模拟函数调用栈。手动模拟递归压栈出栈过程,解除系统栈大小的限制。

3. C 语言的 qsort() 函数?

  • qsort 优先使用归并排序,在数据规模比较小的时候,以空间换时间。

  • 当数据规模比较大时,qsort 会改为快速排序,以三数取中法来选取分区点。

  • qsort 通过在堆上模拟函数调用栈来解决堆栈溢出问题。

  • 当快速排序区间内元素小于等于 4 时,qsort 退化为插入排序。因为在小数据规模下, O(n^2) 时间复杂度算法并不一定比 O(nlogn) 的算法执行时间长。


获取更多精彩,请关注「seniusen」!

转载地址:http://nvozx.baihongyu.com/

你可能感兴趣的文章
深入实践Spring Boot2.4.2 节点和关系实体建模
查看>>
10个巨大的科学难题需要大数据解决方案
查看>>
Setting Up a Kerberos server (with Debian/Ubuntu)
查看>>
用 ThreadLocal 管理用户session
查看>>
setprecision后是要四舍五入吗?
查看>>
shiro初步 shiro授权
查看>>
上云就是这么简单——阿里云10分钟快速入门
查看>>
MFC多线程的创建,包括工作线程和用户界面线程
查看>>
我的友情链接
查看>>
FreeNAS8 ISCSI target & initiator for linux/windows
查看>>
cvs文件提交冲突解决方案
查看>>
PostgreSQL数据库集群初始化
查看>>
++重载
查看>>
Rainbond 5.0.4版本发布-做最好用的云应用操作系统
查看>>
nodejs 完成mqtt服务端
查看>>
在ASP.NET MVC 中获取当前URL、controller、action
查看>>
Spring IoC容器初的初始化过程
查看>>
sql server 触发器
查看>>
[工具]前端自动化工具grunt+bower+yoman
查看>>
自动化测试之WatiN(2)
查看>>