python自学日记18——数据结构与算法(2)
这两天找了很多关于Python讲解数据结构和算法的书和视频,最终确定下来《python数据结构与算法分析》以及北京大学线上课程“数据结构与算法python版”,先看了课程后来发现好像课程结构和这本书差不多,就当配套视频看了。
刚开始还是从一些理论知识开始,虽然也想马上开始敲代码,但是理论内容还是需要掌握一些的,确实有给自己带来一些新的认识。我也一直重视自己关于编程思维方面的训练,正好借助学习算法的机会锻炼一下自己解决问题的能力。
应该认识到的是虽然python现在很热门,但是python只是工具,就像计算机科学并不仅是研究计算机本身,尽管计算机在这一学科中是非常重要的工具,但也仅仅只是个工具。学习python和学习计算机科学一样,研究的对象是问题、解决问题的过程,以及通过该过程得到的解决方案。给定一个问题,计算机科学家的目标是开发一个能够逐步解决该问题的算法。当然算法并不是万能的,某些问题并没有解决方案,认清这一事实很重要。
抽象
抽象是把我们认为对问题不重要的部分抛弃掉,只留下问题的本质的信息就叫做抽象。抽象思维使得我们能够分别从逻辑视角和物理视角来看待问题及解决方案。就像我们使用手机一样,我们会使用通信工具、听音乐、打游戏等,但我们并不需要了解这些功能的实现细节。我们都是从逻辑视角或者使用者视角来看待手机,但是程序员、技术支持人员则从另一个角度看待手机,他们必须知道操作系统的原理、网络协议的配置,以及如何编写各种脚本来控制手机等。他们必须能够控制用户不需要了解的底层细节。
编程上抽象的例子如python的模块,比如我们要计算平方根,我们知道可以导入math模块
import math
math.sqrt(16)
导入math模块,使用sqrt方法我们就知道可以求出16的平方根4,我们并不需要知道平方根究竟是如何计算出来的,只需要知道计算平方根的函数名是什么以及如何使用它,这是过程抽象。
为什么要学习数据结构及抽象数据类型
计算机中的所有数据实例均由二进制字符串来表达。为了赋予这些数据实际的意义,必须要有数据类型,例如整型、浮点型等。简单的计算问题可以由常见的数据类型解决,但我们会发现需要问题及其解决方案都过于复杂。尽管由编程语言提供的简单的控制语句和数据类型能够表达复杂的解决方案,但它们在解决问题的过程中仍存在不足。
因此,为了控制问题及解决方案的复杂度,计算机科学家利用抽象来帮助自己专注于全局,从而避免迷失在众多细节中。通过对问题进行建模,可以更高效的解决问题。模型可以帮助计算机科学家更一致的描述算法要用到的数据。
过程抽象将功能实现细节隐藏起来,从而使用户能够从更高的视角来看待功能。数据抽象的基本思想与此类似。抽象数据类型(ADT)从逻辑上描述了如何看待数据及其运算而无需考虑具体实现。通过这样的抽象,我们对数据进行了一层封装,基本思想是封装具体的实现细节,使它们对用户不可见。
抽象数据类型的实现被称为数据结构。
为何学习算法
各种算法之间往往差异巨大,学习算法可以掌握比较不同算法的分析技巧。要能够区分有解的问题,无解的问题,以及虽然有解但需要过多的资源和时间来求解的问题。
在选择算法时,经常会有所权衡。需要学会如何评估一个解决方案。练习如何找到一个解决方案并且确定其为优秀的解决方案。
最大公约数求解优化
在“python自学日记2——函数调试”中有写过一次求最大公约数的代码如下:
def gcd(a,b):
if a==0:
return b
elif b==0:
return a
elif a%b==0:
print(b)
else:
gcd(b,a%b)
gcd(0,40)
gcd(5,10)
这段代码有点冗余的地方就是不需要判断a是否等于0,因为a等于0的情况在下面的判断中包含了,另外这段代码有另一个问题:print(b)正常显示,return b在gcd(10,5)这种一次整除情况下能显示输出结果,在无法整除的例如gcd(3,4)这种则不显示结果,要注意print和return的区别。
所以改成代码如下:
def gcd1(a,b):
if b==0:
return a
elif a%b!=0:
gcd(b,a%b)
return b #将return移动到最末端
gcd(10,0)
这样代码更精简,而且也不用纠结return b还是print(b)的问题了。