Chapter 6 问题求解和算法设计
6.1 问题求解
问题求解(problem solving): 找到令人困惑的难题的解决方案的行动
A. 如何解决问题
步骤:
step 1: 必须理解问题
step 2: 找到信息和解决方案之间的联系.
如果找不到直接的联系,则可能需要考虑辅助问题.
最终,应该得到解决方案
step 3: 执行方案
step 4: 分析得到的解决方案
策略:
a. 提出问题
当获取一个问题或任务,对它进行提问,知道完全明白要做什么.
一些典型的提问:
` 对这个问题我了解多少?
` 要找到解决方案我必须处理那些信息?
` 解决方案是什么样的?
` 存在什么特例?
` 我如何知道已经找到解决方案?
b. 寻找熟悉的情况
永远不要彻底重新做一件事.如果解决方案已经存在了,就用这种方案.
*c. 分治法
通常,我们会把一个大问题划分为几个能解决的小单元.
B. 应用Polya的问题求解策略
6.2 算法
算法(algorithm): 在有限的时间内用有限的数据解决问题或子问题的明确指令集合.
A. 计算机问题求解
计算领域中的问题求解过程包括四个步骤,即 分析和说明阶段、算法开发阶段、实现阶段、维护阶段
a. 分析和说明阶段 -- 输出清楚的问题描述:
分析: 理解(定义)问题
说明: 说明程序要解决的问题
b. 算法开发阶段 -- 输出的是第一阶段定义的问题的通用解决方案
开发算法: 开发用于解决问题的逻辑步骤序列
测试算法: 执行列出的步骤,看他们是否能真正地解决问题
c. 实现阶段 -- 输出的是计算机可以运行的程序,这个程序实现了这个问题的专用解决方案 -- 算法
编码: 用程序设计语言翻译算法(通用解决方案)
测试: 让计算机执行指令序列.检查结果,修改程序,直到得到正确的答案
d. 维护阶段 -- 在发生错误或改变的时候,返回第一,二或三阶段
使用: 使用程序
维护: 修改程序,使它满足改变了的要求,或者纠正其中的错误
B. 执行算法
C. 开发算法
当前使用的把问题转化为方案的方法有两种,即 自顶向下设计(又称功能分解) 和 面向对象设计(OOD)
它们都是基于分治策略
6.3 伪代码
A. 伪代码的功能
a. 变量: 出现在伪代码算法中的名字,引用的是存储值的位置(文本框).这些名字要能反映出它存放
的值在算法中的角色
b. 赋值: 如果有了变量,就要把值放入变量的方法
可采用下面语句:
Set 某变量 to 值(或其他变量)
某变量 <- 值(或其他变量)
c. 输入/输出: Read/Write 同义的有 Get,Input/Display,Print
Read 变量
Write 变量 ///输出值
Write "something" ///输出字符串
d. 重复(循环/迭代):
使用重复结构可以重复指令
While(重复条件)
执行部分
e. 选择: 用选择结构可以选择执行或跳过某项操作
有 If - Then 和 If - Then - Else 两种版本
f. 注释: //
B. 伪代码实例
Print number1 + " " + number2 //这里 + 是follow by 的便捷符号
6.4 自顶向下设计方法
自顶向下设计(top-down design):
一种程序开发技术,其中问题被分解为更容易处理的子问题
这些子问题的解决方案组合起来构成整体问题的解决方案。
模块(module)/子问题: 一个用于解决问题或子问题的封闭步骤集合
问题和子问题之间是分层结构(又称树形结构)
抽象步骤(abstract step): 细节仍未明确的算法步骤,需要扩展
具体步骤(concrete step): 细节完全明确的算法步骤,无需扩展
排序(sorting): 把列表中的条目按照数字顺序或字母顺序排列
排序关键字(sort key): 用于排序的域
总结 -- 自顶向下的方法可以分解为四个步骤:
分析问题 -> 编写主要模块 -> 编写其他模块 -> 根据需要进行重组和改写
测试算法:
桌面检查(desk checking): 在纸上跟踪一种设计的执行情况
走查(walk-through): 由一个小组手动地模拟一种设计
审查(inspection) : 由团队成员之一逐行读出设计,其他成员负责指出错误的验证方法
6.5 面向对象方法
面向对象的设计方法是用叫做对象的独立实体生成解决方案的问题求解方法,对象由数据
和处理数据的操作构成。面向对象设计的重点是对象以及它们在问题中的交互作用。一旦收集
到了问题中的所有对象,它们就能构成问题的解决方案。
A. 面向对象
面向对象的问题求解方法需要把问题中的类隔离开来
对象之间通过发送消息(调用其他对象的子程序)进行通信
在面向对象的思想中,数据和处理数据的算法绑在一起,因此,每个对象负责自己的处理(行为)。
面向对象设计(OOD)的底层概念是 类(class) 和 对象(object)
对象(object): 在问题背景中相关的事物或实体
对象类(object class) 或 类(class): 一组具有相似属性和行为的对象的描述
域(fields): 类的特定项,可以是数据或子程序
方法(method): 定义了类的一种行为的特定算法
B. 设计方法
分解过程有四个阶段
1. 集体讨论
集体讨论是一种集体行为,为的是生成解决某个特定问题要用到的候选类列表
2. 过滤
确定问题解决方案中的核心类,去除重复的类.另外,也许有两个类到中有许多共同
的属性和行为,那么应当把共同具有的部分集中在一个超类中,这两个类继承这个
超类,再分别附加不同的属性.
3. 场景
则个阶段的目标是给每个类分配责任.最终,责任将被实现为子程序.
在则个阶段,我们感兴趣的只是"任务是什么",而不是"如何执行任务"
责任的类型有两种,即类自身必须知道什么(知识)和类必须能够做什么(行为),
类把它的数据(知识)封装起来,一个类的对象不能直接访问另一个类的数据.
封装(encapsulation): 把数据和行为集中在一起,使数据和行为的逻辑属性
与它们的实现细节分离
4. 责任算法
最终为责任编写算法.由于在面向对象的设计观念中,重点是数据而不是行为,所以
执行责任的算法一般都相当短.
知识责任,通常返回一个对象的变量的内容,或者给另一个对象发送消息来检索它.
行为责任,稍复杂,涉及计算.因此自顶向下设计算法的方法通常也适用于设计责任算法
总结
自顶向下的设计方法 重点在于把输入转化成输出的过程,结果将生成层次化的任务体系结构.
面向对象的设计方法 重点在于要转换的数据对象,结果生成的是层次化的对象体系结构.
面向对象的设计相对更好一些,因为它创建的一些类还可以用于其他背景.
可复用性是面向对象设计的一大优点.
6.6 几个重要思想
A. 信息隐蔽
在设计过程中,高层设计隐蔽了细节.对应每个特定的分层,设计者只考虑与之相关的细节.
信息隐蔽(information hiding): 隐蔽模块的细节以控制对这些细节的访问的做法
B. 抽象
信息隐蔽是隐藏细节的做法,抽象则是隐藏细节的后果.
抽象(abstraction): 复杂系统的一种模型,只包括对观察者来说必需的细节.
数据抽象(data abstraction): 把数据的逻辑概观和它的实现分离开
过程抽象(procedural abstraction): 把动作的逻辑概观和它的实现分离开
控制抽象(control abstraction): 把控制结构的逻辑概观和它的实现分离开
控制结构(control strcture): 用于改变正常的顺序控制流的结构
C. 事物命名
在编写算法时,我们用速记符号表示要处理的任务和信息,即给数据和过程一个名字
这些名字叫做标识符,它们是抽象的一种形式
D. 程序设计语言
程序设计语言(programming language):
用于构造程序(表示成计算机能够理解的指令序列)的规则、符号和专用字集合
程序(program) : 用于执行特定任务的指令序列
语法(syntax) : 规定有效指令的结构的正式规则
语义(semantics): 赋予程序设计语言中的指令含义的一套规则
E. 测试
有算法阶段的测试和实现阶段的测试