2020—2021—1学期 20202422《网络空间安全导论》第四周学习总结

第八章:抽象数据类型与子程序

这一章我们进一步谈论抽象和抽象容器。

一,抽象数据类型:属性(数据和操作)明确地与特定实现分离的容器。简而言之,就是抽象出来的数据的容器。我们从三个方面观察数据。

1,应用(或用户)层是特定问题中的数据的视图。

2,逻辑(或抽象)层是数据值和处理他们的操作的抽象视图。

3, 实现层明确表示处理存放数据项的结构,并用程序设计语言对数据的操作进行编码。这一层设计了数据结构。

二,栈。栈是一种抽象符合结构,只能从一段访问栈中的元素。可以在第一个位置插入元素,也可以删除第一个元素。这种类型的处理称为LIFO,意思是后进先出,比如自助餐厅的餐具架。

另一种描述栈的访问行为的说法是删除的项总是在栈中时间最短的项目。整个LIFO行为都体现在删除操作上。具体而言,插入操作叫push,删除操作叫pop 。我们需要确定的是栈是否为空(isEmpty)。

三,队列。队列也是中抽象结构。插入操作在队列的尾部进行,删除操作在队列的头部进行,与栈是相反的关系称为先进先出,删除的总是在队列中时间最长的项目。

四,列表。列表有三个属性特征:项目是同构的,项目是线性的,列表是变长的

//数组是内嵌结构,列表是抽象结构//

列表也可以被形象化为链式结构。

如果是无序列表,项目将按他们插入的顺序打印。如果是有序列表,项目将被有序的打印出来。

注意:链式结构:一个将数据项和找到下一项位置的信息保存到同一容器的实现方法。

五,树。更复杂的关系,如非线性关系,需要树来表示。

1,二叉树。

二叉树是一种抽象结构,后继节点:子女。原始节点:根。没有子女的节点:叶节点。如果一个节点左边的子节点存在,则这个子节点叫做左子女,右子女也是一样的道理。

注意:a,根据规定,除了根节点外,每个节点都只有一个父母节点。

b,树种每个节点都可被看作一个子树的跟。

2,二叉检索树。

任何节点的值都要大于他的左子树中的所有节点的值,并且要小于他的右子树中发所有节点的值。

这种搜索法与线性结构的二分检索法具有相似性。如果current指向一个节点,那么info(current)指的就是这个节点中的用户数据,left(current)指向左子树根节点,right(current)指向的是右指数的根节点。null说明指针指向空值。

五,图。树中,一个节点至多只有一个指向它的节点,如果去掉这个约束,就得到了图。

1,图:有一组节点和一组把节点连接起来的便构成的数据结构。

其中:

顶点:图中的节点。

边:表示图中的两个节点的链接的顶点对。

无向图:其中的便没有方向的图。

有向图:其中的边是从一个顶点指向另一个顶点。

邻顶点:通过边链接起来的两个顶点。

路径:连接图中两个顶点的一系列顶点。

2,图算法。

a,深度优先搜索。我们想要沿着一条路径尽可能深地访问各个节点,若果没有找到终点则溯回,因此栈是一种储存顶点的合适的数据结构。

b,广度优先搜索。广度优先搜索能用最少的停顿次数从城市X到城市Y。我们尽可能少回溯,采用队列来保存元素的顺序。

c,单源最短路搜索。此处将路径上的边的值(权值)加在一起得到的和最小。

六,子程序。

Insert操作需要一个 列表和一个插入其中的值。Reset 操作需要一个用来重置的列表。MoreItems操作需要一个列表来查看是否有更多元素等待被返回。GetNext操作需要一个输人列表并且返回列表中的下一个元素。这些信息的交流是通过参数列表的概念实现的。

1,参数传递。

a,参数列表( parameter list):程序中两部分之间的通信机制。

b,形参(parameter):列在子程序名后的括号中的标识符。

c,实参(argument):子程序调用中列在括号中的标识符。

调用子程序时传递的实参个数必须与子程序定义中的形参个数相同。由于实参和形参是根据位置匹配的,所以它们的名字不必一致。当需要多次调用一个子程序而每次调用的实参又不同时,这一点非常有用。以这种方式传递的形参通常称为位置形参。

2,值参与引用参数。

a,值参(value parameter):由调用单元传人实参的副本(写在留言板上)的形参。

b,引用参数(reference parameter):由调用单元传入实参的地址(写在留言板上)的形参。

第九章 面向对象设计与高级程序设计语言

一,面向对象方法。

前面说过,之所以先介绍自顶向下设计,是因为它更能反映人们解决问题的方式。如你所见,自顶向下的解决方案对任务进行了分层。每个任务或指定的动作通过其参数列表操作传递给它的数据来生成想要的输出。自顶向下设计的重点就是任务。相反地,面向对象的设计方法是用叫作对象的独立实体生成解决方案的问题求解方法,对象由数据和处理数据的操作构成。面向对象设计的重点是对象以及它们在问题中的交互。一旦收集到了问题中的所有对象,它们就能构成问题的解决方案。

二,面向对象。

  • 对象(object):在问题背景中相关的事物或实体。

  • 对象类(object class)或类(class): 一组具有相似的属性和行为的对象的描述。

  • 域(field):类中的特定项,可以是数据或子程序。

  • 方法(method):定义了类的一种行为的特定算法。

三,设计方法。

我们提出的分解过程有四个阶段。集体讨论(头脑风暴)是确定问题中的类的第一个阶段。在过滤这个阶段中,将回顾集体讨论阶段确定的类,看哪些类是可以合并的以及还缺少哪些类。过滤阶段保留下来的类将在下一个阶段仔细研究。

场景阶段将确定每个类的行为。由于每个类只对自己的行为负责,所以我们称类的行为为责任。这个阶段探讨的是“如果......将会怎么样”的问题,以确保所有的情况都被分析到。当每个类的责任都确定后,它们将被记录下来,同时记录的还有它们必须与之协作(交互)才能履行责任的类的名字。

最后是责任算法阶段,这个阶段将为列出的所有类的责任编写算法。CRC卡就是用来记录这一阶段的类信息的工具。

1,头脑风暴

什么是头脑风暴?字典把它定义为一种集体问题求解的方法,包括集体中的每个成员的自由发言。随着计算机变得越来越强大,能够解决的问题也变得越来越复杂,这种把自己锁在没有窗户的房间中的场景已经过时了。复杂问题的求解需要集思广益,以得到具有创新性的解决方案。 在面向对象的问题求解背景中,头脑风暴是一种集体行为, 为的是生成解决某个特定问题要用到的候选类的列表。在进行广告标语的头脑风暴之前,所有参加者都要先了解产品,同样,在对类进行头脑风暴前,参加者也必须了解问题。每个进入头脑风暴的成员都应该清楚地了解要解决的问题。毫无疑问,在准备过程中,每个成员都会草拟出自己的类列表。

2,过滤。

头脑风暴会生成一份暂时的类列表。下一阶段要根据这个暂时的列表,确定问题解决方案中的核心类。在这份列表中,也许有两个类其实是相同的。这种类重复的现象很常见,因为一个公司不同部门的人员会对相同的概念或实体采用不同的名字。另外,也许列表中有两个类有许多共同的属性和行为,这些共同的属性和行为可以组合在一起。

在这份列表中,也许有的类根本不属于问题的解决方案。例如,如果我们要模拟一一个计算器,那么可能会把用户列为一个可能的类。但实际上用户并不是模拟器中的一一个类,用户只是这个问题之外的一个实体,用于给模拟器提供输人而已。另一个可能的类是“开”按钮。但仔细想一下就会发现,“开”按钮也不是模拟器的一部分,它仅用于启动模拟程序。

在完成过滤之后,这个阶段保留下来的所有类将被传递到下一阶段。

3,场景。

这个阶段的目标是给每个类分配责任。最终,责任将被实现为子程序。在这个阶段,我们感兴趣的只是“任务是什么”,而不是“如何执行任务”。

责任的类型有两种,即类自身必须知道什么(知识)和类必须能够做什么(行为)。类把它的数据(知识)封装了起来,使得一个类的对象不能直接访问另一个类中的数据。所谓封装,就是把数据和动作集中在一起,使数据和动作的逻辑属性与它们的实现细节分离。封装是抽象的关键。不过,每个类都有责任让其他类访问自己的数据(知识)。因此,每个类都有责任了解自身。

封装(encapsulation):把数据和动作集中在一起,使数据和动作的逻辑属性与它们的实现细节分离。

行为的责任看起来更像自顶向下设计中的任务。例如,学生类的一个责任可能是计算它的年级平均成绩(GPA)。在自顶向下设计中,我们会说这个任务是计算特定数据的GPA.在面向对象设计中,我们会说学生类要负责计算自己的GPA。尽管最后的计算代码可能看起来相同,但是它的执行方式却完全不同。在以自顶向下设计为基础的程序中,程序调用计算GPA的子程序,把学生对象作为参数传递。在面向对象的程序中,将给学生类的对象发送消息来计算GPA。这里没有参数,因为得到消息的对象知道自己的数据。

这个阶段输出的是一套分配了责任的类,可能写在CRC卡上。卡上列出了每个类的责任以及每个责任需要协作的类。

4,责任算法。

最终必须为责任编写算法。由于在面向对象的设计观念中,重点是数据而不是动作,所以执行责任的算法一般都相当短。 例如,知识责任通常只返回一个对象的变量的内容,或者给另一个对象发送消息来检索它。动作责任复杂一些, 通常涉及计算。因此,自顶向下设计算法的方法通常也适用于设计动作责任算法。

5,总结。

让我们做个总结: 自顶向下的设计方法重点在于把输人转化成输出的过程,结果将生成任务的体系结构。 面向对象设计的重点是要转换的数据对象,结果生成的是对象的体系结构。

Grady Booch用这样的方法分类:“阅读要构造的软件的说明。如果要编写程序性的代码,就用下划线标出动词;如果要编写面向对象的程序,请标出名词。”

我们建议用波浪线标出名词,用下划线标出动词。名词可以成为对象,动词可以成为操作。在自顶向下设计中,动词是重点;在面向对象设计中,名词是重点。

 

四,责任算法

1,Person类 有两个责任需要分解,即初始化和输出。由于姓名是一个类, 可以让这些类自己进行初始化并输出自身。在面向对象设计中,调用子程序的方法是用对象名加点号再加要调用的方法。

2,Name类 这个类有两个责任,即初始化和输出,它们的算法不同。初始化责任必须提示用户输人姓名,并且算法必须读入姓名。输出责任则必须输出姓和名,并给出合适的标签。

五,翻译过程。

1,编译器:把用高级语言编写的程序翻译成机器码的程序。

2,解释器:输入用高级语言编写的程序,指导计算机执行每个语句指定的动作的程序。解释器在翻译过语句之后会立即执行这个语句。

注意:第二代高级语言分为两种:一种是要编译的,一种是要解释的。要编译的语言发展成了主流,产生了Java。

3,字节码:编译Java源代码使用的标准机器语言。

六,程序设计语言范性。

范性:1,用作模式或模型的实体。2,一组假设、概念、值和实践,构成了共享他们的聚合体观察现实的方式,尤其适用于精神科学。

1,命令式范型

冯·诺依曼顺序指令模型在内存中操作教值,这给了编程语言所用的绝大多数常用模型巨大的影响:命令式模型。在计算软件历史上,行业里具有统治地位的语言都是这种范型,这些语言包括FORTRAN、BASIC、 C、Pascal、C++。在这些范型中,这些程序描述了解决问题的必要处理。因此,这些命令式范型具有顺序执行指令的特征,变量的使用代表了内存地址,而使用赋值语句则改变这些变量的值。

a,面向过程的范型

面向过程编程是一种命令式模型,在这里语句被分组为子程序。一个程序是子程序分层次构成的,每一层执行整个问题求解的一个必要 的特定任务。伪代码示例描述了这种模型。我们编写子程序并且通过向其传递所需数据来完成它们的功能。

b,面向对象的范型

面向对象视角是与对象交互的一种方式。每个对象负责执行它自己的动作。在面向过程的范型中,数据被认为是被动并且被程序所操控的。在面向对象的范型中,数据对象是活跃的。对象和操作对象的代码绑定在一起,使得每个对象负责控制自己的操作。SIMULA和Smalltalk是最先支持面向对象编程的语言。Java和Python是两种新式的面向对象编程语言。

C++和Java是命令式的语言,但就它们的范型而言又是混合的。尽管Java被认为是面向对象的,但是它还是有些面向过 程的特性。C++被认为是面向过程的, 但是它又有面向对象的特征

2,声明式范型。

声明式范型是一个描述结果的模型,但是完成结果的过程则不被描述。在这种范型中有两种基本模型:函数式和逻辑式。

a,函数式模型。

函数式模型基于函数的数学概念。计算通过对函数求值来实现,而问题求解通过函数调用来实现。因此基本的原理是函数的求值,而不是变量和赋值语句。

b,逻辑编程。

逻辑编程基于象征逻辑的原则。这个模型包括了一系列关于对象的事实和一系列关于对象间关系的规则。一个程序包括了向这些对象和关系询问可以通过事实和规则推演的问题。解决潜在问题的算法用逻辑的规则来推演出事实的规则的答案。

七,高级程序设计语言的功能性。

在高级语言中,选择和迭代操作非常简单,但子程序和参数传递则较为复杂。

1,布尔表达式

一个布尔表达式可以是:

a,一个布尔变量

b,一个算术表达式加一个关系运算符,再加一个算术表达

c,一个布尔表达式加一个布尔运算符,再加一一个布尔表达式

迄今为止,在示例中,变量存放的都是数值。布尔变量是内存中的一一个地址,由存放true或false的标识符引用。

布尔表达式( Boolean expression):一个标识符序列,标识符之间由相容的运算符分隔,求得的值是true或false。

2,数据归类。

强类型化:每个变量都有一个类型,只有这种类型的值才能存储到该变量中。

数据类型:一组值以及能够应用于这种类型的值的基本操作集合的说明。

a,数据类型。

数据是表示信息的物理符号。在计算机内部,数据和指令都是二进制位的组合。计算机能够执行一条指令,是因为这条指令的地址被载人了程序计数器,而指令被载入了指令寄存器。被执行的位组合同样可以表示整数、实数、字符或布尔值,关键看计算机如何解释位组合。

大多数高级语言都固有四种数据类型,即整数、实数、字符和布尔型。

整数

整数数据类型表示的是一个整数值的范围。

实数

实数数据类型表示的是特定精度的数的范围,与整数数据类型一样,这个范围由表示实数值的字节数决定。许多高级语言有两种大小的实数。应用于实数的操作与应用于整数的一样。

字符

第3章介绍过,表示ASCII字符集中的字符需要-一个字节,表示Unicode字符集中的字符则需要两个字节。ASCII字符集包括英语字符,是Unicode字符集的子集。对字符进行算术运算是毫无意义的,许多强类型化的语言都不允许进行这种运算。但比较字符却是有意义的,所以可以对字符进行关系运算。

布尔型

布尔数据类型只有两个值——true和false。还可以为布尔变量指定一个布尔表达式。

整数、实数、字符和布尔型称为简单数据类型或原子数据类型,因为每个值都是独立的,不能再分割。上一章讨论了 复合数据类型,即由一组值构成的数据类型。字符串是一种具有复合数据类型的特征的数据类型,但通常被看作简单数据类型。

字符串

字符串是一个字符序列,在某些语言中这个序列通常被看作一个数据值。

b,声明。

声明:把变量、动作或语言中的其他实体与标识符关联起来的语句,使程序员可以通过名字引用这些项目。

保留字: 一种语言中具有特殊意义的字,不能用它作为标识符。

区分大小写:大写字母和小写字母被看作是不同的;两个拼写方法相同但大小写形式不同的标识符被看作是两个不同的标识符。

3,输入/输出结构

在非强类型语言中,输入的格式决定了类型。如果输人出现在引号之间,则它被假定为一个字符串,并以字符串的形式存储。如果输人的是一个数字, 它将被存储为数字。

输出语句创建字符流。输出语句中列出的项目可以是文字值或变量名。文字值是直接在输出语句中写的数字或字符串(或任何语句)。一次处理一个将要输出的值,从而找到标识符或文字的类型。类型确定了如何解释位模式。如果该类型是字符串,则将字符写人输出流。如果该位模式为数字,则该数字将被转换为表示数字的字符,并将字符输出。

在强类型语言中,不管输人输出语句的语法或输人输出流在哪儿,处理的关键在于数据类型,数据类型确定字符是如何被转换为位模式(输人)以及如何被转换为字符(输出)。在非强类型语言中,输人的格式决定了位模式是如何转换的。

9.4.4 控制结构

  • 控制结构:确定程序中的其他指令的执行顺序的指令

嵌套逻辑

在任何控制语句中被执行或跳过的语句可以是简单的语句或块(一组语句),对于这些语句没有任何限制。事实上,被跳过或重复的语句可以包含一个控制结构。选择语句可以在循环结构中被嵌套。循环结构可以在选择语句中被嵌套。选择和循环语句可以在子程序中被嵌套,而子程序可以在循环或选择结构中被嵌套。

异步

  • 异步(asynchronous): 不与计算机中的其他操作同时发生;换句话说,与计算机的动作不同步。

异步处理也叫作事件驱动处理。换句话说,这样的处理是被程序指令序列以外发生的事件所控制。 异步处理经常被用在Java和VB.NET中,但是很少被其他语言所使用

posted @ 2020-11-05 19:24  范秉天  阅读(162)  评论(0)    收藏  举报