第8章 抽象数据类型与子程序
8.1 抽象数据类型
- 抽象数据类型(Abstract Data Type,ADT):属性(数据和操作)明确地与特定实现分离的容器。
- 在计算领域,可以从应用层、逻辑层和实现层这三个方面来观察数据。
1.应用层:特定问题中的数据的视图。
2.逻辑(或抽象)层:数据值(域)和处理它们的操作的抽象视图。
3.实现层:明确表示出了存放数据项的结构,并用程序设计语言对数据的操作进行编码。 - 数据结构(data structure):一种抽象数据类型中的复合数据域的实现。
- 容器(container):存放和操作其他对象的对象。
8.2 栈
- 栈:一种抽象复合结构,只能从 一端 访问栈中的元素。可以在第一个位置插入元素,也可以删掉第一个元素。
- LIFO(Last In First Out):先进后出的设计。
- 另一种描述栈的访问行为的说法是删除的项总是在栈中时间最短的项目。
- 插入操作叫作Push(推进),删除操作叫作Pop(弹出)。
- 注意:1.栈没有长度属性,所以没有返回栈中项目个数的操作。
2.栈不能为空,不然再弹出项目时就会出错。
8.3 队列
- 队列:一种抽象结构,其中的项目从 一端入,从另一端出。
- FIFO(First In First Out):先进先出的设计.
- 队列的插入操作在队列的rear(尾部)进行,删除操作在队列的front(头部)进行。
- 另一种描述队列的访问行为的说法:删除的总是在队列中时间最长的项目。
- 插入操作和删除操作都没有标准的相关术语。
- 能表示插入操作的几个例子:Enqueue、Enque、Enq、Enter和Insert。
- 能表示删除操作的几个例子:Dequeue、Deque、Deq、Delete和Remove。
8.4 列表
- 列表的列是无止境的。
- 列表有三个属性特征:项目是同构的,项目是 线性的,列表是 变长的。
- 项目可以被删除和检索,所以列表中的项目必须能够相互比较。
- 注意:不要把列表误认为是数组,因为数组的结构是 内嵌,列表的结构是抽象,而且列表应用于数组中。
- 链式结构(linked structure):一个将数据项和找到下一项位置的信息保存到同一容器的实现方法。
- 链式结构以节点的概念为基础。其中一个节点由两部分构成: 用户的数据和指向列表的下一个节点的链接或指针。
- 列表的最后一个节点的指针变量存放的是表示列表结束的符号,通常为 null ,用“/”表示。
- 无序列表与有序列表的相互比较:
无序列表:该列表的顺序并不重要,项目只是随意被放入其中。
有序列表:项目之间具有语义关系。除了第一个项目之外所有项目都存在某种 排序关系 。除了最后一个项目,所有项目都有着 相同的关系 。
8.5 树
8.5.1 二叉树
- 二叉树(binary tree):具有唯一起始节点(根节点)的抽象复合结构,其中每个节点可以有两个子女节点,根节点和每个节点之间都有且只有一条路径。
- 根(root):树中唯一的开始节点。
- 叶节点(leaf node):没有子女的树节点。
- 树中的每个节点可以有0个、1个或2个子女。
- 除了规定每个节点至多有两个子女外,二叉树的定义还说明了根节点和每个节点之间有且只有一条路径。
- 除根节点以外,每个节点都只有一个父母节点。
8.5.2 二叉检索树
- 二叉检索树具有二叉树的形状属性,二叉检索树中的节点可以具有0个、1个或2个子女。
- 二叉检索树还具有语义属性来刻画树中节点上的值,即任何节点的值都要大于它的左子树中的所有节点的值,并且要小于它的右子树中的所有节点的值。
- 在二叉检索树中搜索
注意:这种搜索法与线性结构的二分检索法之间的相似性。在线性结构中,通过一次比较操作,就排除了很大一部分数据。
我们从树的根节点开始,沿着根的后继子树前进,直到找到了要找的项目或发现一个空子树为止。 - 构造二叉检索树
- 输出二叉检索树中的数据
8.5.3 其他操作
- 二叉检索法其实和列表具有同样功能的对象,它们的区别在于操作的有效性,而行为是相同的。
8.6 图
- 图(graph):由一组节点和一组把节点相互连接起来的边构成的数据结构。
- 顶点(vertex):图中的节点。
- 边(弧)(edge(arc)):表示图中两个节点的连接的顶点对。
- 无向图(undirected graph):其中的边没有方向的图。
- **有向图(directed graph(digraph)):其中的边是从一个顶点指向另一个顶点(或同一个顶点)的图。
- 邻顶点(adjacent vertice):通过边连接起来的两个顶点。
- 路径(path):连接图中的两个顶点的一系列顶点。
8.6.1 创建图
- 许多信息可以被呈现在图上:顶点、边和权值。
8.6.2 图算法
1.深度优先搜索。
2.广度优先搜索。
3.单源最短路搜索。
8.7 子程序
8.7.1 参数传递
- 参数列表(parameter list):程序中两部分之间的通信机制。
- 形参(parameter):列在子程序名后的括号中的标识符。
- 实参(argument):子程序调用中列在括号中的标识符。
8.7.2 值参与引用参数
- 值参(value parameter):由调用单元传入实参的副本(写在留言板上)的形参。
- 引用参数(reference parameter):由调用单元传入实参的地址(写在留言本上)的形参。
第9章 面向对象设计与高级程序设计语言
9.1 面向对象方法
- 面向对象的设计方法是用叫作对象的独立实体生成解决方案的问题求解方法,对象由数据和处理数据的操作构成。
9.1.1 面向对象
- 对象(object):在问题背景中相关的事物或实体。
- 对象类(object class)或类(class):一组具有相似的属性和行为的对象的描述。
- 域(field):类中的特定项,可以是数据或子程序。
- 方法(method):定义了类的一种行为的特定算法。
9.1.2 设计方法
- 集体讨论:字典把它定义为一种集体问题求解的方法,包括集体中的每个成员的自由方言。但在面向对象的问题求解背景中,集体讨论是一种集体行为,为的是生成解决某个特定问题要用到的候选类的列表。
- 过滤
-
场景
封装(encapsulation):把数据和动作集中在一起,使数据和动作的逻辑属性与它们的实现细节分离。 - 责任算法
- 总结:自顶向下的设计方法重点在于把输入转化成输出的过程,结果将生成任务的体系结构。面向对象设计的重点是要 转换的数据对象 ,结果生成的是对象的体系结构。
9.1.3 一个计算机示例
- 第一步:问题
第二步:集体讨论和过滤
第三步:责任算法
9.2 翻译过程
9.2.1 编译器
- 编译器(compiler):把用高级语言编写的程序翻译成机器码的程序。
- 要编译一个程序,就必须具有这个编译器在特定机器上的机器码版本。想要在多种类型的机器上使用一种高级语言,就要具备这种语言的多个编译器。
9.2.2 解释器
- 解释器(interpreter):输入用高级语言编写得到程序,指导计算机执行每个语句指定的动作的程序。
- 字节码(byecode):编译java源代码使用的标准机器语言。
9.3 程序设计语言的范型
- 范型:用作模式或模型的实体和一组假设、概念、值和实践,构成了共享它们的 聚合体 观察现实的方式,尤其适用于精神学科。
9.3.1 命令式范型
- 面向过程的范型
- 面向对象的范型
9.3.2 声明式范型
- 声明式范型是一个描述结果的模型,但是完成结果的过程则不被描述。
- 这种范型中有两种基本模型:函数式和逻辑式。
- 函数式模型:基于函数的数学概念。计算通过对函数求值来实现,而问题求解通过函数调用来实现。因此基本的原理是函数的求值,而不是变量和赋值语句。
- Scheme是解释型语言,因此结果在声明后立即显示。
- 逻辑编程基于象征逻辑的原则。这个模型包括了一系列关于对象的事实和 一系列关于对象间关系的规则。
- 一个程序包括了向这些对象和关系询问可以通过事实和规则推演的问题。
- 解决潜在问题的算法用逻辑的规则来推演出事实和规则的答案。
9.4 高级程序设计语言的功能性
- 两种伪代码结果————**选择和重复(循环)是命令式语言的标志。
9.4.1 布尔表达式
- 布尔表达式(Boolean expression):一个标识符序列,标识符之间由相容的运算符分隔,求得的值是True或False。
- 一个布尔表达式可以是:
1.一个布尔变量
2.一个算术表达式加一个关系运算符,再加一个算术表达式
3.一个布尔表达式加一个布尔运算符,再加一个布尔表达式
9.4.2 数据归类
- 强类型化(strong typing):每个变量都有一个类型,只有这种类型的值才能存储到该变量中。
- 数据类型(data type):一组值以及能够应用于这种类型的值的基本操作集合的说明。其分为以下几种:
1.整数:整数数据类型表示的是一个整数值的范围,这个范围由表示整数值的 字节数决定。
2.实数:实数数据类型表示的是特定精度的数的范围,与整数数据类型一样,这个范围由表示 实数值的字节数 决定。
3.字符
4.布尔型
5.字符串:字符串是一个字符序列,在某些语言中这个序列通常被看作一个 数据值 。
6.声明(declaration):把变量、动作或语言中的其他实体与标识符关联起来的语句,使程序员可以通过名字引用这些项目。 - 保留字(reserved word):一种语言中具有特殊意义的字,不能用它作为标识符。
- 区分大小写(case sensitive):大写字母和小写字母被看作是不同的;两个拼写方法相同但大小写形式不同的标识符被看作是两个不同的标识符。
9.4.3 输入/输出结构
- Read:表达式负责从外部环境获取一个值,并将其存入程序内的变量。
- Write或Print:表达式负责向人们显示消息。
- 所有输入语句都由三部分组成,即要存放数据的变量的声明、输入语句和要读入的变量名以及数据流自身。
9.4.4 控制结构
- 控制结构(control structure):确定程序中的其他指令的执行顺序的指令。
- 嵌套逻辑:见上章介绍。
- 异步(asynchronous):不与计算机中的其他操作同时发生;换句话说,与计算机的动作不同步。
9.5 面向对象语言的功能性
- 面向对象语言中三个必要的组成部分 封装、继承和多态。
9.5.1 封装
- 封装(encapsulation):实施信息隐蔽的语言特性。
- 对象类或类(问题求解阶段)(object class or class(problem-solving phase)):属性和行为相似的一组对象的说明。
- 对象(问题求解阶段)(object(problem-solving)):与问题背景相关的事物或实体。
- 对象(实现阶段)(object(implementation phase)):类的一个实例。
- 类(实现阶段)(class (implementation phase)):对象的模式。
9.5.2 类
- 实例化(instantiate):创建类的对象。
- 注意:算法声明类的对象只能通过类的子程序(称为方法)访问类的域。
9.5.3 继承
- 继承(inheritance):类获取其他类的属性(数据域和方法)的机制。
9.5.4 多态
- 多态(polymorphism):一种语言的继承体系结构中具有两个同名方法且能够根据对象应用合适的方法的能力。
- 继承和多态结合在一起使程序员能够构造出不同应用程序中可以重复使用的体系结构。
9.6 过程设计与面向对象设计的区别
- 在面向过程的版本中,列表被呈现为传递给子程序的记录,以便子程序可以对其操作。操作它的数据结构和子程序是用户程序的一部分。在 面向对象的版本中,类对象的实现通过封装实现对用户的隐藏。