很多初学者自认数学基础不好,怀疑这将是学习数据结构不可逾越的大山,对学习数据结构没有足够的信心。总的来说,数学基础不是学习数据结构的必备条件,但好的数据基础对学习数据结构大有助益。
这个问题,其实和“英语不好,可以学习编程吗?”同属一类。不可否认,英语基础好对于学习编程确实是很有帮助的,但它并不是学习编程不可跨越的鸿沟。事实上,只有从优秀程序员跃升为顶尖程序员时,英文基础(需要阅读一些英文资料)的桎梏才会凸显出来,但也并非无法克服。数学和数据结构之间的关系也是如此。
注意,英语基础薄弱并不等价于英语 0 基础,如果是这样,那在学习编程的过程中,确实需要适当地恶补一些英语;学习数据结构也是如此,如果数学基础很差(例如仅有小学功底),就需要在学习数据结构的过程中,有意识地恶补一下数学。这里所谓的恶补,不建议读者无目的地单纯学数学知识,而是在学习数据结构的过程中,遇到搞不懂的数学运算,再去刻意地翻阅相关资料。
举个简单的例子,前面已经详细的讲解了如何用“大 O 记法”来评判一个算法的时间复杂度,那么下面 C 语言代码的时间复杂度是多少呢?
i = 1;
while( i < n ){
i = i * 2;
}
对于此段代码来说,我们只需要求出 while 循环中代码(也就是第 3 行代码)执行的次数,即可轻松得到这段代码的时间复杂度。可以看到,循环条件为 i<n,而变量 i 的值每经历一次循环都会翻倍,因此假设有一个临界值 m,能恰好使 2m = n,此时循环将会终止,程序运行结束。
因此,求这段代码的时间复杂度,只需要求出 m 的值即可。这就需要我们具备对数运算的能力,由 2m = n 得 m = log2n,简化 m 的值并最终得出此段程序的时间复杂度为 O(logn)。此时,如果读者无法理解 m 值的由来,就需要恶补一下关于数学中对数运算的相关知识。
当然,对于绝大多数的数学运算,也可以借助计算器或者网络工具来计算得出。事实上,很多和编写代码无关的工作,我们完全不必亲力亲为,要善于运用网络来解决遇到的难题。
其次,一些读者学习数据结构的初衷,仅仅是想将数据结构应用到自己的项目中。这种情况下,数据基础则更显得无关紧要,因为在实际开发中,很多编程语言都提供有集成数据结构中各种存储结构的库或者模块,例如 C++ 中可以使用 STL 标准库,Python 中可以使用 collections 模块等等。这意味着,如果我们所用的编程语言提供有已封装好的数据结构,则只需简单了解数据结构中各个存储结构的特性,然后调用相关的库或者模块,即可实现最初的目的。
通过前面的学习我们知道,数据结构和算法完全是 2 个独立的学科,只是它们相辅相成(可阅读《数据结构和算法的关系和区别》一节)。读者可能会问,学习数据结构肯定是要学习相关算法的,学习算法不需要有一定的数学基础吗?我认为,学习算法更多的是要求我们具备一定的问题分析能力和空间想象力(可以用画图弥补),很少有算法需要较高的数学功底。
总的来说,无论是学习数据结构还是学习算法,只要读者具备一定的编程能力,都可以学会。而至于数学基础的好坏,有更好,没有也无需沮丧,依然可以学习数据结构和算法。