数据结构与算法:python语言描述
第一章:绪论
1.1 计算机问题求解
区分问题和实例
问题是需求,是总,实例是问题的具体体现,是分
编写程序是为了解决问题,程序的每次执行能处理该问题的一个实例
程序开发过程
分析阶段:需求分析,弄清问题,将含糊的需求转化为详细的问题描述
设计阶段:经过分析阶段得到的严格的问题描述,仅仅只是描述,不具有操作性,计算机不能实际操作。这一阶段就是设计出一个解决问题的抽象计算模型
编码阶段:用具体语言来实现上阶段的抽象计算模型
检查测试阶段:检查并测试程序有没有bug,能不能运行
测试/调试阶段:测试这个程序是不是满足功能需要
1.3 算法和算法分析
三个基本概念
问题:一个问题W是需要用计算求解的一个具体需求,是研究和实现算法的出发点
问题实例:问题W的实例w是该问题的一个具体例子,通常可以通过一组具体的参数设定;一个问题是其所有实例的共性
算法:解决问题W的算法A,是对一种计算过程的严格描述。对W的w,实施A描述的计算过程,就能得到w的解
算法的性质:
有穷性:算法必须在有限的长度内解决问题
可行性:算法可以达到目的
确定性:算法的每一步都要有清晰的定义
输入:算法要有0个或多个输入
输出:算法要有1个或多个输出
常见算法设计模式:
枚举法:根据具体问题枚举出各种可能,暴力破解,一般复杂度还蛮高
贪心法:根据问题的信息尽可能作出部分解,基于部分解逐步扩充得到完整的解。未必能得到最好的解
分治法:divide and conquer,将大问题分解成小问题,逐个击破,得到大问题的解
回溯法(搜索法):如果问题很复杂,没有清晰的求解思路,那么用试探的方式求解,选择一个方向求解下去,如果不行就回溯到前面的步骤,选择别的方向。就像Max的能力一样
动态规划法:如果问题的求解需要靠前面的步骤求解积累的信息的话,在后面的步骤根据已知信息,动态选择已知的最好求解路径,并进一步积累信息
分支界限法:回溯法的改良,如果能在试探过程中获得一些信息来排除掉一些路径的话,缩小求解空间,加速问题求解
注意:
评价算法:以上模式只能借鉴,不应教条化
这些模式并不相互隔绝和排斥,多种模式可以有机组合来解决问题
前提:
每一次基本操作只耗费一个单位的时间
计算设备存储数据用一组基本单元,每个单元只能保存固定的一点有限数据
算法分析:针对一个具体的算法,用一种函数关系,以问题规模n为参数,反映该算法在处理规模n的问题实例时需要付出的开销
目的:推导出算法的复杂度,最关键的是构造和求解递归方程
算法开销
三种考虑:
最好情况,一般价值不大,最好情况出现的可能很小
最坏情况:多数考虑这个
平均情况:有时考虑这个
开销度量:
重要的是量级和趋势,在规模很大的情况下,常量因子可以忽略不计
用渐近复杂度函数描述代价,常用的渐近复杂度函数(不同量级):
O(1), O(log n), O(n), O(n log n), O(n^2), O(n^3), O(2^n)
时间代价
基本计算规则:
空间代价基本操作,O(1)
加法规则,即顺序复合。如果一个算法是多个部分的复合,算法的复杂度是每个部分的复杂度之和
乘法规则,即循环结构。循环里面套循环,复杂度乘起来
取最大规则,即分支结构。取复杂度最大的那个分支的复杂度
1.4 数据结构
数据结构及其分类
三个概念:
信息:日常中的一切都是信息
数据:经过编码的信息,即信息的编码表示,指计算机能够处理的符号形式的总和
数据元素:最基本的数据单位
数据结构:数据之间的关联和组合的形式
抽象定义数据结构:D = (E, R)
E是数据结构D的元素集合,是某个数据集合的一个有穷子集
R是D中的E这些元素之间的某种关系
结构性数据结构和功能性数据结构:
结构性数据结构规定了元素之间的相互关系,功能性数据结构不会对元素之间的关系提出任何结构性要求,而是提出功能性要求,最基础的要求比如:支持元素的存储和访问
典型结构性数据结构:
集合:一堆元素的集合,元素之间没有关系
线性结构:元素之间有一种明确的先后关系,即顺序关系
层次结构:元素分属不同的层次,一个上层元素关联着一个或多个下层元素,关系R形成一种明确的层次性,只从上层到下层,通常允许跨层次
树形结构:像树一样,最上层的元素是根元素,除了根元素的每个元素有且仅有一个上层元素与之关联
图结构:元素之间可以有任意复杂的相互关系
功能性数据结构:
栈
队列
优先队列
字典等