分享

图说通常的编程思路(及数据结构与算法、面向过程与面对对象)

 孤独一兵 2016-11-25

-1- 借助于计算机的问题求解过程

客观世界的问题→提取分析→数据、数学模型→设计→数据结构与算法→编码→程序代码(计算机语言)→编译→执行→输出→结束

对于计算机而言,数据的存储与处理是其最本质也是最核心的问题。通常情况下,我们必须先解决数据的存储问题,再讨论数据的处理问题。

数据结构类型:顺序存储结构、链式存储结构、索引存储结构、散列存储结构。

客观世界到计算机世界的映射方法。

程序开发的方法:

1 渐进式程序开发incremental development

1.1 从一个可以工作的程序的主要部分开始,然后小增量式修改程序,这样可以很快定位错误;

1.2 使用临时变量存储中间值,通过打印来检查这些中间值;

1.3 一旦程序能够工作,就可以删除这些“施工架”。然后将多条语句合并为复合语句;

2 封闭与泛化

开发大型程序的一种方法是先开发一次性的临时程序,不断地改进。这样不会让人望而生畏,程序在开发中逐渐进步;

我们在写大型程序时,一般先设计最顶层、最抽象的类和方法,然后逐步实现细节化的类和方法。

凡是能提取一定度量数据,并能通过某种途径对度量数据实施操作的客观存在都可以构成一个对象,且用属性来描述对象的状态,使用方法和事件来处理对象的各种行为。

应用程序一般都是多模块程序,可包含多个程序模块。模块是一个相对独立的程序段,它可以被其他模块所调用,也可以去调用其他的模块。通常,把被其他模块调用的模块称为子程序,把调用其他模块而没有被其他模块调用的模块称为主程序;模块化便于程序的开发、阅读、维护,同时也有利于系统的运行效率的提高;

一个应用程序通常都是由一个主程序和若干个子程序组成。所谓子程序是相对于主程序而言的一个独立的程序文件,可以单独执行,也可以被其他程序调用。

过程与函数将常用代码集中在一起,供应用程序需要时调用,从而提高了程序代码的可读性和操作性;

-2- 通常的编程思路

对于编程来说,虽说面对的问题各不相同,也会选择比较适合的语言,但也还是有一般的规律或思路可以遵循的,面对复杂程序不一样的问题,当然也要做些变通或调整。图说通常的编程思路(及数据结构与算法、面向过程与面对对象)

人类解决问题的方式是当遇到一个问题时,首先从大脑中搜索已有的知识和经验,寻找他们之间有关系的地方,将一个未知问题做适当转换,转化成一个或多个已知问题进行求解,最后集合起来得到原始问题的解决方案。

编写计算机程序实现算法,也就是设计算法程序的第一步就是让计算机理解问题是什么,这就需要建立现实问题的数学模型,建模的过程就是一个对现实问题的抽象过程,通常也伴随一些合理的假设,其目的是对问题进行简化。运用逻辑思维能力,抓住问题的主要因素,忽略将要因素。逐步用更精确的语言描述问题,最终达到用计算机语言能够描述问题为止。建立数学模型之后,第二个要考虑的问题就是输入输出问题,输入就是将自然语言或人类能够理解的其他表达方式描述的问题转换为数学模型中的数据;输出就是将数学模型中表达的运算结果转换成自然语言或人类能够理解的其他表达方式。最后就是算法的设计,其实就是设计一套对数学模型中的数据的操作和转换步骤,使其能演化最终的结果。

数学模型、输入输出方法和算法步骤是编写计算机程序的三大关键因素,对于非常复杂的数学问题,建立数学模型是非常难的事情,比如天文学家研究的“宇宙大爆炸”模型。对于简单的计算机算法而言,建立数学模型实际上就是设计合适的数据结构的问题。所以,输入输出方式和算法步骤都是基于相应的数据结构设计的,相应的数据结构要能很方便地将原始问题转换成数据结构中的各个属性,也要能很方便地将数据结构中的结果以人们能够理解的方式输出。同时,也要为算法转换过程中各个步骤的演化提供使得的支持。使用线性表还是关联结构,使用树还是图,都是设计输入输出和算法步骤时就要考虑的问题。

-3- 数据结构和算法

数据结构是建立解决问题的数据模型的基础,如果不了解数据结构,就没办法建立数学模型,或者建立的模型不合适导致算法演化困难,甚至无法实现。

采用什么样的数据结构由算法的数学模型决定,但是各不相同的数据结构自身的一些特点反过来也会影响数学模型的选择。数学模型是对问题域的高度抽象,而数据结构又是承载数学模型的基础。在简单的算法中,数学模型的定义有时可能简化成数据结构的定义,即使是复杂的数学模型也是要使用相应定义的数据结构来承载。

数据结构和算法,告诉你如何完成常见的任务,如Java的设计者们设计了大量的方法将常用的数据结构和算法封装在里面;

数据结构:作为处理对象的数据的排列方式;对于存储程序结构的计算机,数据如何存储,直接关系到执行能否有效地完成;实际的内存物理结构是,地址:值;对于程序的编码,则是变量:值;(内存与变量的关系)数组就是利用计算机的机械性,地址的递增而形成的一种数据结构,以数据为基础可以定义出堆、栈、链表、二叉树等典型的数据结构;

就像算法中有典型算法一样,在数据结构中也有典型数据结构,它们都是由老一辈程序员发明创造的。这些数据结构其实都是通过程序从逻辑上改变了内存的物理结构,即数据在内存上呈现出连续分布状态。

数据的结构化是为了算法的可实现、简洁、高效。数组、堆、栈、都是一种有序、有结构的数据存储。编程的思路在于有规律的寻找其规律,没有规律的创造条件让其变得有规律,然后应用判断、循环,某语言的函数、语法,可以简单、粗暴的解决问题。

算法:处理问题的步骤,也就是解决问题或完成问题最优的方法或步骤;较少的编码和较少的执行时间;因为计算机的特别是机械性强,速度极快,有优势应用看起来较笨的穷举法;

程序=算法+数据结构

程序={对象}(对象=数据+操作)

算法=操作+控制结构

操作:逻辑运算、算术运算、数据比较、数据传送;

算法的控制结构:顺序、选择、循环;

分类比例处理方法优缺点
数值计算20%数学公式优势:可随机访问;
非数值计算80%数据结构缺点:需要分配一块连续的存储空间;

-4- 非数值计算算法

常用于数据管理、实时控制以及人工智能等应用领域。与数值计算的算法不同,逻辑判断通常在这类算法中处于主导的地位,算术去处则居于相对次要的地位。算法处理的内容也从单纯的数值运算扩展到对数据、图形和字符信息的综合处理。这类算法起步略晚,但发展迅速。“排序”和“查找”是在这类算法中发展比较成熟且为大家所熟悉的两方面;

由于这类算法使用的数据结构一般比较复杂,对算法的设计和选择往往在很大程度上依赖于处理对象所用的数据结构。所以,这类算法的设计通常都与数据结构的选择联系在一起,使问题变得比较复杂。20世纪70年代,Wirth提出“算法+数据结构=程序”的公式,正是反映了非数值计算算法的发展需要。

计算机能够处理的问题一般可以分为两类:数值计算问题和非数值计算问题。

1 数值计算问题,如线性方程求解、矩阵的计算等。这类问题一般需要程序设计的技巧和相应的数学知识,而数据结构方法涉及比较少。

2 非数值计算问题,约占据80%的计算机工作时间。这类问题不再是单单需要数学知识,而且还需要设计合理的数据结构才能高效解决问题。

-5- 面向过程的结构化设计方法学

1 包括结构化分析、结构化设计、结构化编码;

2 确定输入、输出数据结构,使用自项向下的设计方法,列出需要解决的最主要的子问题,然后通过解决每个子问题来解决初始的问题。其本质是功能的分解,将系统按功能分解为若干模块,每个模块是实现系统某一功能的程序单元,每个模块都具有输入、输出和过程等基本特性。输入和输出分别是模块需要和产生的数据,

3 如三个对象对应四部分数据,这四部分数据分别是7个模块交互;

4 模块独立性可以通过两个准则来度量:聚合(Cohesion)和耦合(coupling)。一个聚合程序高的模块只完成软件过程内的一个单一的任务,而与程序其他部分的过程交互作用很小,简言之,一个聚合模块应当(理想地)只做一件事;耦合是对模块间关联程度的度量,模块间联系越多,其耦合性越强,同时表明其独立性越差。

5 缺点:分离了数据与操作之间的内在联系;

-6- 面向对象程序设计方法学

传统的结构程序设计采取的方式是先考虑求解问题的算法,然后再寻找合适的数据结构。即传统的结构程序是:程序=算法+数据结构。算法被认为是描述程序的逻辑实现。提出这个公式的人是瑞士计算机科学家,也是Pascal语言的设计者Niklaus Wirth。他认为算法是第一位的,也就是说在做程序时,首先要确定是怎么样对数据进行操纵,然后再决定使用什么样的数据结构。所以的传统的结构程序设计中程序是通过算法加上数据结构来实现的。

面向对象的软件开发思想认为程序是由对象组成的,而所有的这些程序代码又都是是放在类中的。面向对象软件开发的首要任务是找到解决该问题的对象,寻找对象的一个比较简单的方法就是在分析过程中找出现的名词。

对象之间通过方法改变自身的状态并且可以发送消息来进行相互通信,因此,在找到对象之后,下一步就是查找动词,找到对象应该负责完成什么样的任务。最后就可以把对象的行为(程序设计中的方法)和状态(程序设计中的变量)封闭到相应的类中;

(有点类似于代数的设未知数,建立方程求解);

这样,软件开发人员可以根据自己的需要调用相关对象的变量和方法,而不必关心这个对象和方法是如何实现的。所以面向对象的程序设计中程序是通过对象和消息的传递来实现的。

实际上,在面向对象的软件开发过程中,一个对象并不是承担的任务越多越好。如果创建一个对象含有复杂的逻辑和数据结构,那么势必会给代码的编写和程序的调试带来很多问题。所以在创建对象的时候,要尽量创建一个可以执行较小任务功能的对象, 这样更有利于代码的编写和程序的调试;

与传统的结构程序设计关注算法不同,在面向对象的思想中,程序员更关心的是使用这个对象的接口来完成所需要完成的任务,对对象内部的具体实现并不是十分关心。这就像使用计算机的时候,关心的是CPU、硬盘、电源这些是不是符合自己的要求,至于它们内部到底是怎么实现的并不是计算机使用者所关心的。

传统的过程化程序设计,必须从顶部的main函数开始编写程序。在设计面向对象的系统时没有所谓的顶部。而是从设计类开始,然后再往每个类中添加方法。

识别类的简单规则是在分析问题的过程中寻找名词,而方法对应着动词。

OO=objects+classes+inheritance+communication with messages

如果一个程序系统只有对象和消息两个概念,程序设计就是建立一个彼此能发消息的对象集合,我们说这就是面向对象程序设计。

1 针对问题域做面向对象分析,找出问题示解所需要的各种相关对象与类;

2 与系统提供的类库相匹配,找到已有类。

3 若无完全匹配的类,则从相近的类中派生出新的子类。然后进行修正与补充,使之与问题求解所需要的类相吻合。

4 苦既无相近的类,也无匹配的类,则只好设计新的类(新类也可以入库);

5 等所需的类都有了以后,给指定类发消息(赋初值),生成程序的对象集;

6 给对象发消息,对象与对象之间发消息,完成计算。

传统的面向过程的程序设计是围绕着功能实现的过程而进行的。在面向过程的程序设计模式下,首先要为解决某个问题确定一个算法,为该算法构造适当的数据结构,将算法和数据结构用计算机语言描述出来,程序结构是过程化的分级结构形式。在这种程序设计中,数据与操作需要分别设计,重点放在对数据进行操作的过程上。一旦数据发生变化,需要及时修改与之相关的程序模块。数据与操作过程的分离容易造成代码的可重用性差及维护代价高。

面向对象的程序设计是一种先进的程序设计技术,其核心思想是封装。首先提取要解决问题中所需要的数据,然后分析出对这些数据需要进行的操作,最后将数据与操作封装(encapsulation)在一起形成一个整体(即对象)。在这种程序设计中,数据与操作作为一个整体进行设计,这种方法将提高代码的可重用性,减少程序设计的工作量,方便维护。

面向对象程序设计者的任务包括两个方面。

(1)设计对象,即决定把哪些数据和操作代码“封装”在一起;

(2)怎样通知有关对象所需完成的任务,即如何发送消息。程序设计者如同一个总调度,不断地向各个对象发出命令,让这些对象活动起来,完成自己范围内的操作

对象的操作可通过修改对象的属性值或执行对象的方法完成。

面向过程的程序设计要求用户要考虑程序设计的全过程,正确书写整个程序的代码;面向对象的程序设计:把客观世界看成一系列相互关联的对象,每个对象都有其属性及允许的各种操作;程序员主要考虑如何创建对象和创建什么样的对象,并设计必要的程序代码;每个对象都有描述其特征的属性及其附属于它的行为;

现实世界事物的抽象:

1 实体entity--数据模型---实体用数据来描述,实体名(属性名1…);

2 对象object:属性(数据)、事件、方法;,将属性和操作封装在一起

对象至少有两个要素;一是从事活动的主体,二是活动的内容;从计算机的角度看,一个对象应该包括两个要素:一是数据,二是需要进行的操作。对象就是一个包含数据以及与这些数据有关的操作的集合。在程序设计中,对象是由数据及可以对这些数据施加的操作结合在一起所构成的独立实体。也就是说,对象就是把数据和对这些数据的操作放在一起,作为一个相互依存不可分割的整体。对象是对客观事物的表示或描述,一个对象具有自身的属性(数据)和可为自己或别人做的工作功能(操作),它能通过发送消息与其他对象进行通信,协同完成任务。

The End

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多