2019-2020-1学期 20192427《网络空间安全导论》第四周学习总结
第八章 抽象数据类型与子程序
8.1 抽象数据类型
1.抽象数据类型(Abstract Data Type,ADT):属性(数据和操作)明确地与特定实现分离的容器。
容器(container):存放和操作其他对象的对象。
2.设计的目标是通过抽象减小复杂度。
3.在计算领域,可以从应用层、逻辑层和实现层这三个方面观察数据。
4.实现层涉及了数据结构。
数据结构(data structure):一种抽象数据类型中的复合数据域的实现。
8.2 栈
1.栈是一种抽象复合结构,只能从一端访问栈中的元素。可以在第一个位置插入元素,也可以删除第一个元素。
2.Push(推进):插入操作
Pop(弹出):删除操作
3.栈没有长度属性,所以没有返回栈中项目个数的操作。
8.3 队列
1.队列也是一种抽象结构,队列中的项目从一端入,从另一端出。插入操作在队列的rear(尾部)进行,删除操作在队列的front(头部)进行。
2.Enqueue、Enque、Enq、Enter和Insert都可以表示插入操作。
Dequeue、Deque、Deq、Delete和Remove都可以表示删除操作。
8.4 列表
1.列表有三个属性特征:项目是同构的,项目是同构的,项目是线性的,列表是变长的。
线性:每个项目除了第一个都有一个独特的组成部分在它之前,除了最后一个也都有一个独特的组成部分在它之后。
2.不要把列表误认为是数组,数组是内嵌结构,列表是抽象结构。
3.列表也可以被形象化成链式结构,链式结构以节点的概念为基础。
4.一个节点由两部分构成:用户的数据和指向列表的下一个节点的链接或指针。列表的最后一个节点的指针变量存放的是表示列表结束的符号,通常为null,用“/”表示。
链式结构(linked structure):一个将数据项和找到的下一项位置的信息保存到同一容器的实现方法。
8.5 树
8.5.1 二叉树
1.二叉树(binary tree):具有唯一起始节点(根节点)的抽象复合结构,其中每个节点可以有两个子女节点,根节点和每个节点之间都有且只有一条路径。
2.根(root):树中唯一的开始节点。
3.叶节点(leaf node):没有子女的树节点。
8.5.2 二叉检索树
1.树类似于一个无序列表。要在树上找到一个项目,我们必须检查每一个节点,直到找到想要的那一个,或者发现它并不在树上。
2.二叉检索树就像已排序的列表,节点间存在语义排序。
3.二叉检索树具有二叉树的形状属性,此外,二叉检索树还具有语义属性来刻画树中节点上的值,即任何节点的值都要大于它的左子树中的所有结点的值。
4.如果current指向一个节点,那么info(current)指的就是这个节点中的用户数据,left(current)指向的是current的左子树的根节点,right(current)指向的是current的右子树的根节点。null是一个特殊值,说明指针指向空值。因此,如果一个指针是null,那么这个子树就是空的。
显然,二叉检索树的搜索效率玉树的形状有直接关系。
树的形状是由项目插入树的顺序决定的。
8.5.3 其他操作
1.二叉检索树其实是和列表具有同样功能的对象,他们的区别在于操作的有效性,而行为是相同的。
2.一个空树有0个节点,任意一个树有1加上左子树的节点个数和右子树的节点个数。
8.6 图
1.树是表示存在的体系结构中关系的有效方式,也就是说,一个节点之多只有一个指向它的节点(它的父母)。如果去掉这种约束,就得到了另一种数据结构--图。
2.图(graph):由一组节点和一组把节点相互连接起来的边构成的数据结构。
顶点(vertex):图中的节点。
边(弧)(edge(arc)):表示图中两个节点的连接的顶点对。
临顶点(adjacent vertice):通过边连接起来的两个顶点。
路径(path):连接图中两个顶点的一系列顶点。
3.无向图(undirected graph):其中的边没有方向的图。
有向图(directed graph(digraph)):其中的边是从一个顶点指向另一个顶点(或同一个顶点)的图。
8.6.1 创建图
许多信息可以被呈现在图上:顶点、边和权值。
创建一个表格需要以下操作:
•在表格中添加一个顶点
•在表格中添加一条边
•在表格中添加一个权值
8.6.2 图算法
1.深度优先搜索
当我们试图在两个顶点间寻找路径时,用栈来储存访问的顶点。用深度优先搜索来检查第一个与起点相邻的顶点。如果它是终点,则搜索结束。否则,检查所有与第一个顶点相邻的顶点。同时,我们需要存储其他和起点相邻的顶点,随后需要的时候会用到它们。如果不存在一条从与起点相邻的第一个顶点出发的路径,那么我们回到顶点,尝试第二个顶点、第三个顶点,以此类推。
2.广度优先搜索
在广度优先搜索中,我们想要回溯到尽可能远,以找到从最初的顶点出发的路径。因此栈不再是一个适合寻找较早路径的数据结构。我们采用队列来保存元素的顺序。
3.单源最短路搜索
最小行程次数的航线并不意味着是最短的总距离。最短路遍历必须说明在搜索过程中城市间的公里数(边权值的和),而不是像深度优先搜索和广度优先搜索那样。我们想要检索离当前顶点最近的顶点,也就是说,与此顶点相连的边权值最小的顶点。我们称这种抽象容器位优先队列,被检索的元素是在队列中拥有最高优先度的元素。
8.7 子程序
1.许多子程序都是高级语言或语言附带库的一部分。
2.Insert操作需要一个列表和一个插入其中的值。
3.Reset操作需要用一个用来重置的列表。
4.MoreItems操作需要一个列表来查看是否有更多元素等待被返回。
5.GetNext操作需要一个输入列表并且返回列表中的下一个元素。
这些信息的交流是通过参数列表的概念实现的。
8.7.1 参数传递
1.参数列表(parameter list):程序中两部分之间的通信机制。
2.形参(parameter):列在子程序名后的括号中的标识符。
3.实参(argument):子程序调用中列在括号中的标识符。
4.可以把形参看作子程序中使用的临时标识符。当子程序被调用时,调用单元会把真正的标识符的名字发送给子程序。子程序中的动作则是用形参定义的。当动作执行时,实参将逐个替代形参。
5.当子程序被调用时,它将得到一个实参列表(就像把实参列表写在了子程序的留言板上)
8.7.2 值参与引用参数
1.传递参数的基本方式有两种,即通过值传递和通过引用(或地址)传递。
2.值参(value parameter):由调用单元传入实参的副本(写在留言板上)的形参。
3.引用参数(reference parameter):由调用单元传入实参的地址(写在留言板上)的形参。
4.要访问一个引用参数,子程序必须访问留言板上列出的地址中的内容。要访问一个值参,子程序只需要访问留言板自身的内容即可。
小结
•列表、栈、队列、树和图都是有用的抽象复合结构。所有抽象复合元素结构都有插入和删除元素的操作。列表和树还有在结构中查找元素的操作。
•列表和树有着同样的属性:元素可以被插入、删除和检索。
•列表、栈、队列荷属都仅仅是容器结构,但图更为复杂。一个丰富的数学算法可以被应用到吐的信息中。我们一斤探讨过其中的三种:广度优先搜索、深度优先搜索和单源最短路搜索。
•子程序声明使得子算法可以独立实现。
第九章 面向对象设计与高级程序设计语言
9.1 面向对象方法
面向对象的设计方法是用叫作对象的独立实体生成解决方案的问题求解方法,对象由数据和处理数据的操作构成。
面向对象设计的重点是对象以及它们在问题中的交互。一旦收集到了问题中的所有对象,它们就能构成问题的解决方案。
9.1.1 面向对象
1.对象(object):在问题背景中相关的事物或实体。
2.对象类(object class) 或 类(class):一组具有相似的属性和行为的对象的描述。
3.域(field):类中的特定项,可以是数据或子程序。
4.方法(method):定义了类的一种行为的特定算法。
9.1.2 设计方法
•我们提出的分解过程有四个阶段:集体讨论阶段、过滤阶段、场景阶段、责任算法阶段。
1.集体讨论阶段
确定问题中的类的第一个阶段
2.过滤阶段
回顾集体讨论阶段确定的类,看哪些类是可以合并的以及还缺少哪些类
3.场景阶段
确定每个类的行为
由于每个类只对自己的行为负责,所以我们称类的行为为责任。
封装(encapsulation):把数据和动作集中在一起,使数据和动作的逻辑属性与他们的实现细节分离。
4.责任算法阶段
将为列出的所有类的责任编写算法。
CRC卡就是用来记录这一阶段的类信息的工具。
5.总结
面向对象设计的重点是要转换的数据对象,结果生成的是对象的体系结构。
9.1.3 一个计算机实例
责任算法:
1.Person类:有两个责任需要分解,即初始化和输出。由于姓名是一个类,可以让这些类自己进行初始化并输出自身。在面向对象的设计中,调用子程序的方法是用对象名加点号再加要调用的方法。[eg.name.initialize()]
2.Name类:这个类有两个责任,即初始化和输出,它们的算法不同。初始化责任必须提示用户输入姓名,并且算法必须读入姓名。输出责任则必须输出姓和名,并给出合适的标签。
9.2 翻译过程
使用高级语言,我们要采用其他软件工具协助翻译过程。
9.2.1 编译器
1.编译器(compiler):把用高级语言编写的程序翻译成机器码的程序。
2.要编译一个程序,就必须具有这个编译器在特定机器上的机器码版本。想要在多种类型的机器上使用一种高级语言,就要具备这种语言的多个编译器。
9.2.2 解释器
1.解释器(interpreter):输入用高级语言编写的程序,知道计算机执行每个语句指定的动作的程序。
2.与汇编器和编译器只是输出机器码且机器码在单独执行不同的是,解释器在翻译过语句之后会立即执行这个语句。可以把解释器看作理解编写程序所使用语言的模拟器或虚拟机。
3.第二代高级语言可以分为两种,一种是要编译的,一种是要解释的。FORTRAN、COBOL和ALGOL是要编译的语言;Lisp、SNOBOL4和APL是要解释的语言。
4.为了达到最佳可移植性,Java被编译成一种标准机器语言--字节码
字节码(bytecode):编译Java源代码使用的标准机器语言。
5.存在标准的机器语言是因为:一种名为JVM(Java虚拟机)的软件解释器接受字节码程序,然后执行它。也就是说,字节码不是某个特定硬件处理器的机器语言,任何具有JVM的机器都可以运行编译过的Java程序。
JVM:为执行字节码程序设计的假想机。
9.3 程序设计语言的范型
1.范型:
- 用作模式或模型的实体
- 一组假设、概念、值和实践,构成了共享它们的++聚合体++观察现实的方式,尤其适用于精神学科。
2.有两种主要的范型,分别是命令的和声明的,在每种中都有很多子范型。
9.3.1 命令式范型
1.FORTRAN、BASIC、C、Pascal和C++都是命令式范型。
2.这些命令式范型具有顺序执行指令的特征,变量的使用代表了内存地址,而使用的赋值语句则改变这些变量的值。
3.面向过程的范型:
面向过程编程是一种命令式模型,在这里语句被分组为子程序。我们编写子程序并通过向其传递所需数据来完成他们的功能。
4.面向对象的范型
•面向对象视角是对象交互的一种方式。每个对象负责执行它自己的动作。在面向过程的范型中,数据被认为是被动并且被程序所操控的。
•在面向对象的范型中,数据对象是活跃的。对象和操作对象的代码绑定在一起,使得每个对象负责控制自己的操作。
•SIMULA和Smalltalk是最先支持面向对象编程的语言。Java和Python是两种新式的面向对象编程语言。
9.3.2 声明式范型
声明式范型是一个描述结果的模型,但是完成结果的过程则不被描述。在这种范型中有两种基本模型:函数式和逻辑式。
1.函数式模型:基于函数的数学概念。计算通过对函数的求值来实现,二问题求解通过函数调用来实现。
最常见的函数范型语言是Lisp、Scheme(Lisp的一种衍生语言)和ML。
2.逻辑编程:基于象征逻辑的原则。这个模型包括了一系列关于对象的事实和一系列关于对象间关系的规则。一个程序包括了向这些对象和关系询问可以通过事实和规则推演的问题。
3.PROLOG是第三代逻辑编程语言,包含三种语句:一种声明了对象及对象之间关系的事实;一种定义了对象及对象之间关系的规则;第三种询问对象及对象之间关系的问题。
在PROLOG系统中,常量以小写字母开头,变量以大写字母开头。事实上,我们以一个常量代替一个变量来询问事实真相。
9.4 高级程序设计语言的功能性
两种伪代码结构--选择和重复(循环)是命令式语言的标志。
9.4.1 布尔表达式
1.布尔表达式(Boolean expression):一个标识符序列,标识符之间由相容的运算符分隔,求得的值式true或false。
2.一个布尔表达式可以是:
- 一个布尔变量
- 一个算术表达式加一个关系运算符,再加一个算术表达式
- 一个布尔表达式加一个布尔运算符,再加一个布尔表达式
3.布尔变量是内存中的一个地址,由存放true或false的标识符引用。
4.关系运算符是比较两个值的运算符。下表总结了六种关系运算符以及各种高级语言用于表示它们的符号:
符号
含义
示例
计算法则
< 小于 Number1<Number2 如果Number1小于Number2,为true,否则为false
<= 小于等于 Number1<=Number2 如果Number1小于等于Number2,为true,否则为false
大于 Number1>Number2 如果Number1大于Number2,为true,否则为false
= 大于等于 Number1>=Number2 如果Number1大于等于Number2,为true,否则为false
!=或<>或/= 不等于 Number1!=Number2 如果Number1不等于Number2,为true,否则为false
=或== 等于 Number1=Number2 如果Number1等于Number2,为true,否则为false
5.两个算术表达式之间的关系运算符是询问两个表达是之间是否存在这种关系,例如:xValue<yValue是一个断言,即xValue小于yValue。如果xValue确实小于yValue,那么这个表达式的结果是true;如果xValue大于或等于yValue,那么结果为false。
9.4.2 数据归类
1.强类型化(strong typing):每个变量都有一个类型,只有这种类型的值才能存储到该变量中。
2.数据类型(data type):一组值以及能够应用于这个类型的值的基本操作集合的说明。
3.大多数高级语言都固有四种数据类型,即整数、实数、字符和布尔型。
- 整数:整数数据类型表示的是一个整数值的范围,这个范围由表示整数值的字节数决定。有些高级语言提供几种范围不同的整数类型,允许用户根据特定问题选择最适合的类型。应用于整数的操作是标准的算术运算符和关系运算符。
- 实数:实数数据类型表示的是特定精度的数的范围,与整数数据类型一样,这个范围由表示实数值的字节数决定。许多高级语言有两种大小的实数。
- 字符:对字符的运算是毫无意义的,但比较字符大小却是有意义的,所以可以对字符进行关系运算。
- 布尔型:布尔数据类型只有两个值--true和false。还可以为布尔变量指定一个布尔表达式。
- 整数、实数和布尔型称为简单数据类型或原子数据类型,因为每个值都是独立的,不可再分割。
- 字符串:一个字符序列,在某些语言中这个序列通常被看作一个数据值。
- 我们使用单引号圈起字符,用双引号圈起字符串。有些高级语言可以采取同样的符号圈起字符和字符串。
声明(declaration):把变量、动作或语言中的其他实体与标识符关联起来的语句,使程序员可以通过名字引用这些项目。
4.保留字(reserved word):一种语言中具有特殊意义的字,不能用它作为标识符。
5.C++、Java、python和VB.NET是区分大小写的。
6.区分大小写(case sensitive):大写字母和小写字母被看作是不同的;两中拼写方法相同但大小写形式不同的标识符被看作是两个不同的标识符。
7.C++和Java用分号来结束语句。VB.NET则利用一行的节为或者注释符号来结束语句。
9.4.3 输入/输出结构
9.4.4 控制结构
1.控制结构(control structure):确定程序中的其他指令的执行顺序的指令。
2.嵌套逻辑:在任何控制语句中被执行或跳过的语句可以是简单的语句或块(一组语句),对于这些语句没有任何限制。事实上,被跳过或重复的语句可以包含一个控制结构。选择语句可以在循环结构中被嵌套。循环结构可以在选择语句中被嵌套。选择和循环语句可以子啊子程序中被嵌套,而子程序可以在循环或选择结构中被嵌套。
3.异步处理:程序必须识别用户点击鼠标的行为,处理该点击然后继续运行。这种类型的处理叫作异步的。
异步(asynchronous):不与计算机中的其他操作同时发生;换句话说,与计算机的动作不同步。
异步处理也叫事件驱动处理。
9.5 面向对象语言的功能性
9.5.1 封装
1.封装(encapsulation):实施信息隐蔽的语言特性。
2.对象类或类(问题求解阶段)(object class or class(problem-solving phase)):属性和行为相似的一组对象的说明。
3.对象(问题求解阶段)(object(problem-solving phase)):与问题背景相关的事物或实体。
4.对象(实现阶段)(object(implementation phase)):类的一个实例。
5.类(实现阶段)(class(implementation phase)):对象的模式。
9.5.2 类
实例化(instantiate):创建类的对象。
9.5.3继承
继承(inheritance):类获取其他类的属性(数据域和方法)的机制。
9.5.4多态
多态(polymorphism):一种语言的继承体系结构中具有两个同名方法且能够根据对象应用合适的方法的能力。
9.6过程设计与面向对象设计的区别
小结
•面向对象设计的重点是确定问题中的对象,并根据对象的属性和行为把它们抽象(分组)成类。
•汇编器可以把汇编语言程序翻译成机器码。
•存在多种高级程序设计语言的模型。
•布尔表达式是关于程序状态的断言。
•程序中的每个变量都有自己的数据类型。