python数据结构与算法——ch1导论

翻译用python解决算法问题ch1
1.1 目标

  • 回顾计算机科学、编程以及解决问题的思想;
  • 理解抽象化及其在解决问题中扮演的角色
  • 理解和实现抽象的数据结构
  • 复习python编程语言

1.2 入门
自从第一台计算机诞生以来,人们对编程的思考经历了很大变化,最开始的程序需要通过跳线和交换设备将人类的编程语言转换为机器语言。就像社会生活的许多方面一样,计算技术的发展也为计算科学家提供了越来越多的工具和平台用于他们的实践活动。越来越快的处理器、高速的网络以及大容量存储设备在带来很多优势的同时也创造了一个复杂的螺旋,计算机科学家们必须对技术的发展对适当的导向。在这个快速的进化过程中,有很多基本原则是始终没有改变的,计算科学所关注的问题是用计算机来解决实际问题。
毫无疑问你会花费大量时间学习解决问题的基本技能,使得你对自己问题建模和构建坚决方案的能力感到自信。你也会发现编写一个计算机程序经常是复杂的,问题的复杂性和解决方案的复杂性会趋向于掩盖解决问题过程中的基本思想。
本章的剩余内容强调了 两个重要的领域。首先,文章回顾了计算机科学以及数据结构和算法研究中必须符合的框架,特别是我们为什么需要研究这些主题以及如何理解这些主题能够帮助我们更好地解决问题。其次,我们复习了python编程语言。虽然我们没法提供具体详尽的参考,但是我们会给出一些基本结构体的例子和解释以及一些在之后章节中会用到的思想。

1.3 什么是计算机科学
计算机科学通常是难以定义的,这可能是由于名称中“计算机”一词使用不够恰当。正如你可能了解到的,计算机科学并不是单纯地研究计算机,尽管计算机在这个领域中扮演了支持性的角色,但是计算机仅仅是一个工具。
计算机科学研究实际问题、解决问题以及解决问题过程中用到的方案。给定一个问题后,一个计算机科学家的目标是开发一个算法,算法就是一步接一步的指令列表,这些指令用于解决问题中可能出现的各种情况。算法是一个有限的过程,如果遵照算法步骤执行最终可以解决问题。从这个角度来说,算法就是解决方案。
计算机科学可以被认为是对算法的研究。然而,我们必须小心面对这样的事实:有些问题可能没有解决方案。尽管证明这个问题超出了本文的陈述范围,但是一些问题是无法解决的事实对于研究计算机科学的人来说是非常重要的。现在,我们可以给出计算机科学的完整定义,就是研究问题的解决方案以及那些没有解决方案的问题。
在描述问题和解决方案的时候通常会提到一个词“可计算性”(computable)。如果存在一个算法来解决问题,那么我们就说这个问题是可计算的。一个对计算机科学的另一种定义是研究可计算的不可计算问题以及算法是否存在的科学。无论如何你会发现“计算机”这个词根本没有出现,解决方案被认为是和机器独立的。
计算机科学本身就是在研究解决问题的过程,同时也是在研究“抽象化”(abstraction)。抽象化使得我们可以从逻辑和物理的角度来看待问题和解决方案。这个基本思想对于我们来说是一个通用的示例。
想象一下你今天可能开车去上学或者上班。作为一个司机,你会产生特定的交互来利用汽车达到特定的目的。你进入车内、插入钥匙、发动车辆、移动、刹车、加速以及通过转向等操作驾驶车辆。从抽象化的观点来说,我们认为你在从一个逻辑的角度来看待汽车。你在使用汽车设计者所提供的函数来实现特定的功能将你从一个地点移动到另一个地点。这些函数有时候被叫做接口。
在另一方面,修理你汽车的机械师从不同的角度看待汽车。她不仅知道如何驾驶,还必须了解实现这些我们认为理所当然的操作背后的所有具体细节。她需要理解发动机是如何工作的,传动齿轮是如何运转的,温度是如何控制的……这就是物理角度,发生在引擎盖下的具体细节。
同样事情发生在我们使用计算机的过程中。大部分人用计算机来写文档、收发邮件、浏览网页、播放音乐、存储图像以及玩游戏,不需要知道任何关于这些应用如何工作的具体细节。他们从逻辑或者用户的角度来看待计算机。计算机科学家、程序猿、技术支持人员以及系统管理员从不同的角度看待计算机。他们必须知道操作系统是如何运行的、网络协议是如何配置的以及如何编写不同的脚本实现特定功能。他们必须能够控制更底层的细节。
这些例子的共同点在于抽象化的用户(有时候称为客户端)只要知道接口是如何工作的而不需要知道具体的实现细节。这个接口就是我们作为用户和底层的复杂实现进行通信的方式。我们把python中的math模块作为抽象化的另一个例子。只要我们导入这个模块,我们就能执行计算功能,比如:

>>> import math
>>> math.sqrt(16)
4.0
>>>

这是一个程序抽象的例子。我们没有必要知道平方根是如何求解的,我们只要知道函数名称以及如何使用它。如果我们正确导入了这个模块,我们就可以认为函数能够返回正确的结果。我们知道有人实现了求解平方根的算法并且只要知道如何使用它就可以了。这个过程有时候被叫做“黑盒模型”。我们仅仅定义一个接口:函数的名称、需要的参数以及返回值,具体的细节隐藏在黑盒中。

1.4 什么是编程
编程就是采用一种算法并将其编码成一种符号,一种编程语言,以便它可以由计算机执行的过程。尽管存在许多编程语言和许多不同类型的计算机,但重要的第一步是需要有解决方案。没有算法,就没有程序。
计算机科学不是编程的学习。但是编程是计算机科学家所做的一个重要部分。编程往往是我们为解决方案创建表示的方式。因此,这种语言表达及其创造过程成为学科的基础部分。
算法根据表示问题实例所需的数据以及产生预期结果所需的一系列步骤来描述问题的解决方案。编程语言必须提供表示过程和数据的符号方法。为此,语言提供了控制结构和数据类型。
控制结构允许以简便而明确的方式表示算法步骤。最低限度的情况,算法需要执行顺序处理的结构,用于决策的选择以及用于重复控制的迭代。只要语言提供了这些基本语句,就可以用于算法表示。
计算机中的所有数据项均表示为二进制数字串。为了赋予这些字符串的含义,我们需要有数据类型。数据类型提供了对这个二进制数据的解释,这样我们就可以根据解决问题的意义来思考数据。这些底层的内置数据类型(有时称为基本数据类型)为算法开发提供了构建模块。
例如,大多数编程语言为整数提供数据类型。计算机内存中的二进制数字串可以解释为整数,并给出我们通常与整数(例如23,654和-19)相关联的典型含义。另外,数据类型还提供了数据项可以参与的操作的描述。对于整数,加法,减法和乘法等操作是常见的。我们期望数字类型的数据可以参与这些算术运算。
我们经常遇到的困难是实际问题及其解决方法非常复杂。这些简单的,语言提供的结构和数据类型虽然足以代表复杂的解决方案,但通常会使解决问题的过程处于不利的地位。我们需要方法来控制这种复杂性并协助创建解决方案。

1.5 为什么学习数据结构和抽象数据类型
为了解决问题的复杂性和解决问题的过程,计算机科学家们使用抽象概念来让他们专注于“大局”,而不会迷失在细节之中。通过创建问题域的模型,我们能够使用更好,更高效的问题解决过程。这些模型允许我们描述我们的算法将以更一致的方式处理问题本身的数据。
之前,我们将程序抽象视为隐藏特定功能的细节的过程,用户或客户从高层访问它。我们现在把注意力转向类似的想法,即数据抽象。抽象数据类型(有时缩写为adt)是对我们如何查看数据以及允许执行的操作的逻辑描述,而不考虑它们将如何实现。这意味着我们只关心数据所代表的内容,而不关心它最终如何构建。通过提供这种抽象级别,我们创建了一个数据封装。这个想法是通过对实现细节的封装,在用户的角度来看隐藏了细节,这被称为信息隐藏。
图2显示了一个抽象数据类型是什么以及如何操作的图片。用户使用由抽象数据类型指定的操作与接口进行交互。抽象数据类型是用户与之交互的shell。实现隐藏在更深层次,而用户并不关心实现的细节。
python数据结构与算法——ch1导论_第1张图片

1.6 为什么学习算法
计算机科学家通过经验学习,我们通过参考别人解决问题的方案然后用来解决自己的问题。接触不同的解决问题的技术、研究不同的算法是如何设计的可以帮助我们解决以后遇到的问题。掌握了一定数量的不同算法后,我们就能够形成一种“模式识别”的能力,在下一次遇到一个类似的问题时就能使用更好的方案解决。
不同算法通常差异很大。就像之前提到的求平方根的算法,完全可以有不同的算法来求解平方根。有的算法可能会比其它算法使用更少的资源,有的算法可能需要比其它算法多花10倍的时间,我们希望能够通过某些方式来比较不同的解决方案。尽管不同的方法都是有效的,但是有的方法可能会比其它的方法好。我们通常会推荐更有效的算法或者说运行更快、内存占用更少的算法。在我们研究算法的过程中,我们会学习算法的分析方法。这些分析方法让我们从算法本身的特性来做对比,而不是从实现算法的语言或者计算设备的角度对比。
在最坏的情况下,我们可能会遇到棘手的问题,这意味着没有算法能够在现实的时间内解决问题。能够区分有解决方案的问和那些没有解决方案的问题,以及存在解决方案但需要太多时间或其他资源才能合理工作的问题,这一点很重要。
很多时候我们需要确定一个折衷方案。作为计算机科学家,除了解决问题的能力外,我们还需要知道并理解解决方案评估方法。最后,通常有很多方法可以解决问题。找到一个解决方案,然后决定它是否是一个好的解决方案是我们需要不断挑战任务。

1.7 复习基本的python语法
这部分我们会复习一下python的编程语言,同时为之前提到的内容提供一个更详细的例子。如果您是python的初学者,或者需要更多关于这部分的知识,我们建议您去查找一些相关的资源,比如Python官方API或者python教程。我们的目标是让您重新认识这门的语言,并强化一些概念,这些概念对后面的章节至关重要。
python是一门现代化的,面向对象的,简单易学的编程语言。它拥有功能强大的内建数据类型和容易使用的控制结构。由于python是一种解释型语言,因此只需查看和描述交互式会话即可轻松回顾。
你应该记得熟悉的>>>解释符,然后就会明白python的结构。比如:

>>> print("Algorithms and Data Structures")
Algorithms and Data Structures
>>>

上面例子中显示了提示符,print函数,显示结果和下一个提示符。

1.8 数据结构入门
我们在之前说过,python支持面向对象的编程范例。这就意味着python将数据作为解决问题过程中的焦点。不管在python还是其它面向对象的语言中,我们定义一个类(class)来说明数据是什么样的,能做什么操作。类和抽象的数据类型相似,类的用户只能看到数据项的状态和行为。在面向对象的编程语言中,数据项被称为是对象。一个对象是一个类的实例化表示。
1.8.1内置的原子数据类型
我们从原子数据类型开始回顾python的语法。Python有两种主要的内置数字对象用于实现整型和浮点型的数据类型。这两个python类叫做int和float。标准算术运算,+, - ,*,/和**(指数运算)可以与括号一起使用,用来改变运算符优先级。其它比较有用的运算符有取余运算%和整除运算//。注意两个整数相除结果是一个浮点数;整数除法截去所有小数部分只返回商的整数部分。例如:

print(2+3*4)
print((2+3)*4)
print(2**10)
print(6/3)
print(7/3)
print(7//3)
print(7%3)
print(3/6)
print(3//6)
print(3%6)
print(2**100)

运行结果分别是

14
20
1024
2.0
2.33333333333
2
1
0.5
0
3
1267650600228229401496703205376

python中还支持布尔数据类型,可能的取值为TrueFalse,基本的布尔操作有and,ornot
bool数据类型同时支持比较运算符,下面列出比较运算符。
python数据结构与算法——ch1导论_第2张图片
基本逻辑运算示例:

print(5==10)
print(10 > 5)
print((5 >= 1) and (5 <= 10))

运行结果为:

False
True
True

python中变量命名对大小写敏感,命名时最好采用容易理解的方式。
一个python变量在赋值时创建,变量保存数据的指针而不是数据本身:

>>> theSum = 0
>>> theSum
0
>>> theSum = theSum + 1
>>> theSum
1
>>> theSum = True
>>> theSum
True

赋值语句theSum=0创建了theSum变量,其中保存了数据0的引用,正如图三所示:
图三
通常情况下,赋值语句将”=”右边的内容赋值给左边,如下图:
python数据结构与算法——ch1导论_第3张图片

1.8.2内置的集合数据类型
除了数字和布尔类,python还有很多功能强大的内置集合数据类。列表(lists)、字符串(strings)和元组(tuples)

1.9 输入和输出
1.10 控制结构
1.11 异常处理
1.12 定义函数
1.13 python中面向对象编程:定义类
1.14 总结
1.15 关键术语
1.16 问题讨论
1.17 编程练习

你可能感兴趣的:(python数据结构与算法——ch1导论)