性能
| 算法 | 最坏情况下的运行时间的增长数量级 | 最坏情况下的运行时间的增长数量级 | 平均情况下的运行时间的增长数量级 | 平均情况下的运行时间的增长数量级 | 内存使用 |
|---|---|---|---|---|---|
| 查找 | 插入 | 查找命中 | 插入 | ||
| 顺序查询 | N | N | N/2 | N | 48N |
| 二分查找 | lgN | N | lgN | N/2 | 16N |
| 红黑树 | 2lgN | 2lgN | lgN | lgN | 64N |
| 拉链法散列表 | <lgN | <lgN | N/(2M) | N/M | 48N+32M |
优缺点
| 使用的数据结构 | 优点 | 缺点 |
|---|---|---|
| 顺序查找(链表) | 适用于小型问题 | 对于大型符号表很慢 |
| 二分查找(二分查找) | 最优的查找效率和空间需求,能够进行有序性相关的操作 | 插入操作很慢 |
| 二叉查找树 | 实现简单,能够进行有序性相关操作 | 没有性能上界的保证,链接需要额外的空间 |
| 平衡二叉查找树(红黑树) | 最优的查找和插入效率,能够进行有序性相关的操作 | 链接需要额外的空间 |
| 散列表 | 能够快速地查找和插入常见类型的数据 | 需要计算每种类型的数据的散列,无法进行有序性相关的操作,链接和空节点需要额外的空间 |
测试
我将测试代码放在https://github.com/chennuo0125-HIT/Algorithms-Fourth-Edition-Cpp.git,测试样例是统计一段文字中出现频率最高的单词,测试步骤如下:
git clone https://github.com/chennuo0125-HIT/Algorithms-Fourth-Edition-Cpp.git
cd Algorithms-Fourth-Edition-Cpp
mkdir build && cd build
cmake ..
make
../bin/test_search ../data/tale.txt
结果:
sequential_search algo find "the" with largest times 7989 and cost time 11.7608[sec] //顺序查找
binary_search algo find "the" with largest times 7989 and cost time 0.567544[sec] //二分查找
bst_search algo find "the" with largest times 7989 and cost time 0.56815[sec] //二叉查找树
rbt_search algo find "the" with largest times 7989 and cost time 0.137314[sec] //红黑树
ht_search algo find "the" with largest times 7989 and cost time 0.043644[sec] //散列表
结论:
从结果中可以看出散列表的速度是最快的,其次是红黑树,二分查找树和二分查找差不多,顺序查找速度特别慢.所以在不考虑有序性相关的操作之外,散列表无疑是最优选择,而且实现简单.其次才考虑红黑树,虽然性能很好,但实现复杂.
使用总结
相对二叉查找树,散列表的优点在于代码更简单,且查找时间最优(常数级别,只要键的数据类型是标准的或者简单到我们可以为它写出满足均匀性假设的高效散列函数即可).二叉查找树相对于散列表的优点在于抽象结构更简单(不需要设计散列函数),红黑树可以保证最坏情况下的性能且它能够支持的操作更多(如排名、选择、排序和范围查找).根据经验法则,大多数程序员的第一选择是散列表,在其他因素更重要时才会选择红黑树.
参考
以上结论来自于<<算法第4版>>
版权声明:本文为weixin_37835423原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。