工程中选择数据结构和算法的依据

1. 时间、空间复杂度不能和性能划等号

时间、空间复杂度不是时间执行和内存消耗的精确值。它们只是表示了随着数据量的增长,时间、空间的增长趋势。

代码的执行时间有时不跟时间复杂度成正比。我们常说算法是O(nlogn),O( n 2 n^2 )这些都是基于大数据量(例如 50 >50 ),在小数据量的时候可能O( n 2 n^2 )比O(nlogn)更快。

对于不同问题,不同算法之间不能做复杂度比较。复杂度只能表征不同算法在处理同类型数据、同样问题时候的算法 优劣。

2. 抛开数据规模谈数据结构和算法都是“耍流氓”

数据规模小,算法之间的优越性体现不出来。
代码执行频率过低,算法优化的效果体现不出来。
代码执行频率不高,并且是非核心代码,选择简单、易懂的数据结构和算法。

流入100以内的字符串比较用暴力匹配就挺好。使用KMP等更容易出问题,增加维护成本。

3.结合数据特征和访问方式选择数据结构

例如Trie树在字符串有公共前缀的情况下使用能提高搜索效率。如果数据之间都没有公共前缀,用Trie树就不合适了。

例如图使用邻接表存储还是邻接矩阵存储,看图是稀疏矩阵吗。如果是,就用邻接表,不是就用邻接矩阵存储。

4. 区别对待 IO 密集、内存密集和计算密集

IO密集:例如数据存储在磁盘上,需要每次读取。通过减少IO的次数,提高性能 。例如数据库查询是IO密集型,减少数据库操作次数,提高性能。

计算密集:代码执行效率的瓶颈在CPU执行上。例如已经将数据加载到内存中。优化的时候要减少逻辑计算复杂度。例如用位运算代替加减法。

内存密集:计算操作都比较简单,代码执行效率的瓶颈在数据加载到内存。例如字符串比较。因此,在选择数据结构和算法的时候,需要考虑是否能减少数据的读取量,数据是否在内存中连续存储,是否能利用 CPU 缓存预读。

5.善用语言提供的类库,避免重复造轮子

6.有目的的优化,不过度优化

在有必要的时候,在核心代码、在执行频率高的代码做优化。

我们要学会估算。估算能力实际上也是一个非常重要的能力。我们不仅要对普通情况下的数据规模和性能压力做估算,还需要对异常以及将来一段时间内,可能达到的数据规模和性能压力做估算。这样,我们才能做到未雨绸缪,写出来的代码才能经久可用。

当真的要优化代码的时候,一定要先做 Benchmark 基准测试。这样才能避免你想当然地换了一个更高效的算法,但真实情况下,性能反倒下降了。

发布了148 篇原创文章 · 获赞 35 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/flying_all/article/details/100112016
今日推荐