数据结构与算法 Python
1. 求解问题的计算之道
自古以来人类在各个方面都会遇到许多未知的事物。比如螃蟹能不能吃,什么是无理数,为什么云不会掉下来,怎样实现公平正义。* 总而言之,**这些问题都可以归纳为what,why,how的问题。**在这些问题中,有些我们已经解决,有些还未解决,有些无法解决。
为了解决这些问题,我们也运用了很多手段和方法。比如直观感觉,占卜,计算,模拟仿真…等等。最终我们发现,利用数学方法解决问题是非常准确高效的。因为数学本身符号表达准确严谨,并且推理系统非常严密。虽然数学不是万能的,但它仍是我们最好的工具之一。于是大数学家希尔博特提出了一个问题:能否找到一种基于有穷观点的能行方法,来判定任何一个数学命题的真假。之后研究证明,希尔伯特的计划最终被证明无法实现,但“能行可计算”概念成为计算理论的基础。由此诞生了用以计算的“图灵计算模型”,它可以将人们使用纸笔进行数学运算的过程进行抽象,由一个虚拟的机器代替人类进行数学运算。
2. 图灵计算模型 Turing Machine
图灵机有以下三个部分组成:
- 无限长的纸带。纸带可以类比传统计算机的内存(Memory)。纸带上有一个个小方格子,格子里可以写入一些symbols。
- 读写头。它可以做到以下三种操作
- 从一个小方格中读出symbol。
- 清除一个小方格中的内容,或直接写入新的symbol来覆盖原有的数据
- 向其他方格移动
- 控制器。可以根据program中制定的规则决定读写头的具体操作
因此在任意的program中,图灵机都会有五个部分组成一条控制规则。
- 当前状态
- 当前读入的symbol
- 将当前格子改为什么symbol
- 如何移动读写头
- 改变为什么状态
3. 算法和计算复杂性
问题的分类:
- What:是什么(面向判断和分类问题)
- Why:为什么(面向求因和证明问题)
- How:怎么做(面向过程与构建问题)
这些问题中,有些我们可以解决,有些不能解决。在能解决的问题中,有些可以用计算解决,有些不能。
用任何“有限能行方法”能解决的问题,都是“可计算的”。
- 在What(分类问题)中,可以通过树状的判定分支解决。从根节点向下进行判断。
- 在Why(证明问题)中,可以通过有限的公式序列来解决。数学定理证明从不证自明的公理出发,一步步推理得出最后待证明的定理。
- 在How(过程问题)中,可以通过算法流程解决。算法与数据结构主要研究的内容。
3.1 计算复杂性
基于有穷观点的能行方法的“可计算”概念,仅仅涉及到问题的解决是否能在有限的资源内完成,但并不关心具体要花费多少计算步骤或多少储存空间。而计算复杂性研究问题的本质将各种问题按照难易程度分类,并不关心问题的具体解决方案。
3.2 算法分析
占用计算资源的大小是算法好坏的主要评判标准。计算资源分为计算时间和计算空间
- 算法所消耗的时间通常用时间复杂度来描述
- 算法所消耗的空间通常用空间复杂度来描述
随着硬件技术的不断发展,一般算法的主要限制条件还是算法的计算时间。因此我们通常主要考虑算法的时间复杂度。
我们通过**“大O符号表示法**来表示时间复杂度:
其中表示每行代码执行次数之和(假设每行代码的运行时间大致相等,这样就可以表现算法的运行时间)。例如:
for i in range(0,n)
a += 1
a += i
这段代码第一行执行一次,第二三行分别执行n次,那么这个算法的时间复杂度为。如果这个例子中的无限大的话,那么公式中的常数1和倍数2并没有太大意义。因此,在大O符号表示法中,我们可以忽略这些不重要的东西。则。
常见的时间复杂度量级有:
- 常数阶
- 对数阶
- 线性阶
- 线性对数阶
- 平方阶
- 立方阶
- K次方阶
- 指数阶
在我们实际检测算法运行时间时,Python可以用time
模块检测运行时间。例如:
import time % 导入time模块
start = time.time() % 记录开始时间
你的算法。。。
end = time,time() % 记录结束时间
print(end- start) % 输出所用时间,单位为秒