6作业树通用性证明

 

 

 

《树型软件工程方法》之系列博文6

 

作业树通用性证明

 

 

 


 

 

 

 

TREESOFT


 

 

中国人为什么不可以有自己的软件工程方法及其开发工具平台!

这是介绍《树型软件工程方法》的系列博文,请按文章标题所带的编号顺序阅读,否则你会看不懂本文。


6作业树通用性证明         

 

    乞今为止,对作业树的讨论可以说是相当全面了,既有工程实例,又有原理叙述。然而,人们还是会追问,任何问题的求解算法都能 用作 业树来表示吗?作业树用于软件设计是通用的吗?因为长期以来人 们都认为,只有某些问题的求解算法才能形成分层嵌套的程序,才 能被 表示成树型。现在我们将从理论上证明:任何问题的求解算法都是 分层 嵌套的,都可以用作业树来表示。 

6.1分治的概念

   众所周知,分治与递归是算法设计与分析学科的基础理论,是算法设计与分析的根本。现在我们将要阐明,问题递归处理的理论依据就是分治法。我们知道,采用分治策略解决一个问题有三个步骤:

   1) 将问题分解为若干个小的子问题。每个子问题与大问题同型,但规模更小。

   2) 递归地解决这些子问题。即按同样的分治策略求解子问题,将子问题分解成更小的子问题,直至问题的规模达到微不足道,简单到十分易于求解。

   3) 将子问题的解合并,获得大问题的解。反照递归的顺序自底向上,将求出的子问题的解合并为一个更大规模问题的解,逐步求出原问题的解。

   上述三条,就是分治法的具体表述。实际上,可以将分治法分为两步:

   递归分解问题:自顶向下递归地分解问题,直至子问题简单易解;

   递归求解问题:自底向上递归地合并子问题的解,直至求得原问题的解。

 

6.2 Tq递归分解

对于问题的分解,分治法要求子问题的模型与大问题的模型相同,这是保证能递归地分解和求解的关键。在问题递归处理中,无论是原问题模型还是子问题模型,都是Tq型态树,也就是博文《作业树设计原理》中的图5.5所示的型态树。为便于观察,我们将图5.5拷贝于图6.1。要阐明作业树的通用性,首先就要阐明Tq模型的通用性,我们将从下面四个方面来阐述。

 

6.1 Tq型态树

   (1) 任何有解的问题都可依据算法表示成Tq型态树。

   我们知道,Tq型态树是结果倒推法的图形表示。对于有解的Sq,其总有求得结果时的状态条件,亦即“求解已结束”。将“求解已结束”逻辑求反,就得到Tq型态树根节点中的“求解未结束”逻辑表达式。然后,就可整理出“求解未结束”状态条件控制下的“可执行操作”(可能为空),放置于Tq型态树根节点左儿子的首部。至于Tq型态树中待求解的下级Sq,就是待分解的下级问题。至此就可得出结论:任何有解的问题都可依据算法表示成Tq型态树。

   (2) Tq的递归分解是可以连续进行的。

   按照分治法,问题的递归分解必须连续进行。在问题递归处理中,问题的连续分解就是对Tq的递归分解,直至抵达不含控制的Sq。所谓对Tq的递归分解,即对Tq根节点左口的下级Sq进行结果倒推,就形成了下级Tq。根据上一条的结论,只要下级Sq有解,就可被表示成Tq型态树。假定在对Oq按问题递归处理分解的过程中,存在某一级Tq的递归分解不能进行,即该Tq的下级Sq不能进行结果倒推。这就意味着这个Sq是无解的,因为凡有解的Sq都可以采用结果倒推法形成Tq型态树。然而,只要存在无解的下级Sq,就意味着Oq无解,这与“Oq有解”的已知条件矛盾。所以,对有解OqTq递归分解总是可以连续进行的。

   (3) 顺序作业是最简单的问题。

   按照分治法,对问题的递归分解要抵达最简单的问题。在问题递归处理中,对Tq的递归分解终止在不含控制的Sq,即在最低一级Tq的下级Sq中是不含控制的。由图6.1可以看出,所谓“Tq的下级Sq中不含控制”,实际上是最低一级Tq的左子树中没有下级Sq,只有可执行操作。按照可执行操作生成的程序段中都是顺序语句,称为顺序作业,也就是作业树的叶节点。显然,顺序作业是由Tq递归分解形成的最简单的问题,是不含控制的线性问题。

6.3 Tq递归求解

   按照分治法,原问题的解是通过自底向上递归地合并子问题的解得的。如前所述,作业树中每一个节点都对应着一个Tq,叶节点可以认为是没有下级问题的Tq。在作业树中“自底向上递归地合并子问题”,也就是“自底向上地递归地合并Tq”。这样的递归合并求解过程,也就是运行作业树。现在,我们将作业树运行规则拷贝如下(参见博文《冒泡排序程序的结构化设计》),以便剖析作业树的运行机理。

 [作业树运行规则]

(1) 节点开始,无条件地先运行其左子树。

(2) 向前处理

2.1) 对于双向条件节点,如果它的逻辑表达式的值为“真”就运行其左子树,为“假”则运行其右子树。

2.2) 对于单向条件节点,若其逻辑表达式的值为“真”则运行其唯一拥有的左子树。

2.3) 对于循环节点,只要其逻辑表达式的值为“真”就(循环)运行其唯一拥有的左子树。

2.4) 对于控制结节点,运行完相应的控制节点后,该控制节点中口所连接的作业子树必须无条件地被运行。

2.5) 按上述规定子树递归地自上而下运行,直至叶节点运行完或不满足向前(向下)处理时则转向(3)。

(3) 后退返回

3.1) 从不能继续向前处理的节点开始,沿向前处理所形成的路径逐个节点后退返回。

3.2) 如果退至条件节点则继续后退。

3.3) 如果退至循环节点。若不满足循环条件则继续后退;若满足循环条件则转(2)再次向前处理。

3.4) 如果已退至节点,则无条件执行根节点右儿子中唯一的结束语句,结束作业树的运行。

   由上述运行规则和问题递归处理可知,当父节点的“求解未结束”为“真”时,控制就进入儿子节点;而当儿子节点的“求解已结束”为“真”时,控制就会退出儿子节点。注意,这里不用“求解未结束”为“假”,而用“求解已结束”为“真”。的确,在逻辑关系上它们是互为求反的,但在问题求解的实施上不能互为求反。“求解未结束”为“假”也含有“不求解”的意义,即问题可能并未被求解。而“求解已结束”为“真”,表明问题已经求解出了结果。对于三类基本控制,它们的“求解已结束”情况分别如下。

   1) 单向条件节点。仅当运行过其左子树后并退出单向条件节点时,“求解已结束”才为“真”。如果其“求解未结束”为“假”而退出本节点,说明并未运行过其左子树,属于出错退出,并非“求解已结束”为“真”退出。

   2) 循环节点。仅当运行过其左子树后并退出循环节点时,“求解已结束”才为“真”。与单向条件控制略有不同,循环控制的确是当“求解未结束”为“假”时才退出的。但只要运行过循环节点的左子树后再出现“求解未结束”为“假”,此仍属于“求解已结束”为“真”退出。如果进入循环节点时就有“求解未结束”为“假”(一次都没有运行过循环体),说明并未运行过其左子树,属于出错退出,并非“求解已结束”为“真”退出。

   3) 双向条件节点。当“求解未结束”为“真”运行过其左子树后退出,与单向条件节点相同,属于“求解已结束”为“真”的退出。如果“求解未结束”为“假”,就必须运行其右子树。连继嵌套的双向条件控制且连续有“求解未结束”为“假”,就必须连续运行相应的右子树。这种情况下,仅当运行过某节点的左子树或最后一级双向条件节点的右儿子(必定是顺序节点)后退回时,才算是“求解已结束”为“真”;否则(没有运行过任何左子树)其就是在并未求解过问题的情况下退出,属于出错退出,并非“求解已结束”为“真”退出。

   关于双向条件控制的情况似乎复杂了一点,实际并不难理解。如果“求解未结束”连继为“假”而退出,显然没有求解过问题,当然属于出错退出。

   4) 控制结。由于接于中口的子树是要无条件执行的,与其父节点的控制无关。所以,无论控制节点的运行是正常退出还是出错退出,都必须运行其中子树。我们可以利用控制结的这一特点,打印输出说明控制节点是否是正常退出的信息。

   5) 叶节点。由于叶节点没有儿子,不存在是否运行过下属子树的问题。只要运行过叶节点自身,即是“求解已结束”为“真”。

   6) 起始节点。起始节点没有控制逻辑表达式和中口。控制进入起始节点后先强令运行其左子树,相当于执行了“求解未结束”为“真”;控制退回至起始节点时,自然就是“求解已结束”为“真”,但控制不能后退,而是强令运行其右儿子后结束Oq的求解。

   在作业树的运行机理上,运行过控制节点的左子树是“求解已结束”为“真”的充要条件。

   上述结论给出了“求解已结束”为“真”的充要条件。而“求解已结束”为“真”又是控制后退的充要条件,所以运行过左子树也是控制后退的充要条件。显然,要运行左子树必须有“求解未结束”为“真”,即“求解未结束”为“真”是运行左子树的必要条件,也是“求解已结束”为“真”的必要条件。由于任何控制节点都必须以“求解未结束”为“真”作为“求解已结束”的前提条件,使得控制必须一直向前求解问题,直至到达叶节点。而叶节点没有“求解未结束”控制,其被运行后便是“求解已结束”为“真”,控制便由此开始后退,并陆续遇到“求解已结束”为“真”的充要条件,使得控制连续后退,直至作业树的根节点。

   由Tq的定义可知,所谓“运行过某控制节点的左子树”,也就是运行以该控制节点为根的Tq。通过上面对作业树运行机理的剖析可以看出,作业树的运行机理是:

   自上向下Tq递归地前进,抵达叶节点后又Tq递归地返回。

   我们知道,作业树的运行是在遍历编程成程序后运行实现的。程序中的逻辑控制是用算法语言表述的,编译系统根据算法语言的定义生成机器语言。由此可见,作业树的运行逻辑是由机器保证的。

   依据作业树的运行机理,作业树中最左的叶节点(不含控制的Tq)必定最先被求解,然后从左向右自底向上Tq递归地求解。在这个过程中,以任意节点为根的Sq的求解,都是在合并以该节点左、右儿子节点为根的Tq的解的基础上求得的。这正是分治法中的递归求解问题:自底向上递归地合并Tq(子问题)的解,直至求得Oq(原问题)的解所以说,作业树所表示的问题求解过程也是符合分治法的。

6.4 通用性结论

   至此我们已经证明:

   问题递归处理完全符合分治法。任何有解的问题都可以被表示成Tq,进而自顶向下Tq递归地分解直至线性问题,自底向上Tq递归地求解直至原问题的解。作业树是表示问题求解算法的通用模型。

   问题递归处理是设计作业树的方法,作业树是表示问题求解算法的通用模型。但是,问题递归处理并不是问题求解的通用算法,不同的问题求解算法会形成不同的作业树。

   这里说“作业树是表示问题求解算法的通用模型”,即是说作业树是通用的。这个结论的成是建立在“分治法是通用的”基础上的。然而,并没有人证明过,任何问题的求解都可以采用分治法。这么大而泛的题目,恐怕也不好证明。此前我曾说过,当一个命题无法从正面证明时,最简单可靠的方法就是反面举例推翻她。在推翻之前我们认可命题的成立,以便在工程中运用她,同时有机会寻找可能存在的反例。只要没有出现过反例,我们就一直可以令她为工程服务。

6.5 历史与现状

   作业树属于函数级程序结构设计工具,又称这一级的设计为程序详细设计。程序流程图是人们一直使用至今的详细设计工具,作业树是在程序流程图的基础上创立的。1973年,由美国的NassiShneiderman合作创造了N-S图。同年,日本的日立公司提出了PAD图。N-S图和PAD图都是程序详细设计的图形工具,也都是从程序流程图演化而来的。这两种图形工具都得到了一定程度的推广应用,也是最具代表性的详细设计工具。现在,我们来将作业树与这两类图做个比较。图6.2画出了冒泡排序算法的N-S图和PAD图表示。逻辑上,这两种表示方式与博文《冒泡排序程序的结构化设计》中的图1.7的作业树是一样的。

   1) 共性

   显然,作业树、N-S图和PAD图都能表示算法的详细程序设计,而且所表示的程序结构都是分层嵌套的。

   2) 特性

   三者都是围绕基本控制来构建图型。所不同的是:N-S图和PAD图都是将控制与顺序段分离,按照控制逻辑自外向内(N-S)或自左向右(PAD)进行延伸设计。作业树则是把控制与顺序段整合在一起,定义为一个作业。含有控制的称为控制作业,不含控制的称为顺序作业。作业树以作业为设计单元,按照控制逻辑自顶向下延伸设计。

   3) 方便性

   N-S图是盒状图,设计过程中很可能因外层矩形过小致使内层不便于继续延伸。补救的办法是作一个标志,然后再画一个N-S子图。PAD图是自左向右的排列式延伸,其不会象N-S图那样受到空间的限制。PAD图和N-S图都有一个共同的缺陷,对图形的修改极为不便,多数情况下只有重画。

   作业树不存在设计空间受限的问题,修改也很方便。在辅助系统的帮助下,采用子树剪接的方式就可以实现所需的修改。这是以作业或作业子树为设计单元所带来的好处。

 6.2 冒泡排序算法的N-S图和PAD图表示

   4)可读性

   应该说,N-S图和PAD图的可读性都比流程图好,可以一目了然地看出程序内部的控制关系。

作业树的可读性比N-S图和PAD图更好。不但可以直观地看出程序内部的控制逻辑,而且可以看出每个作业的功能。加上配有注释说明,作业树的可读性近乎完美。人们也许会说,控制作业的顺序部空间受限,作业树中往往把其中的顺序语句另行列出,这大大影响了作业树的可读性。实际上,不仅作业树有这个缺陷,N-S图和PAD图同样也有这个缺陷。要在作业树的图形上解决这个问题很简单,如图6.3所示。这里将图1.7中控制作业的顺序部画于上部,这样顺序部的空间就不受限制了。


6.3 与图1.7等价的作业树

   可以看出,图6.3虽然增加了空间,但看上去很不美观。特别是因作业节点的大小不一,不便于标准化,当然就不便于辅助设计。所以,我们还是不打算采用这种方式,仍采用前述的标准方式。致于制图空间的受限间题,在辅助设计工具的帮助下可以得到满意的解决。如博文《冒泡排序程序的结构化设计》中的图1.8所示,只要用鼠标点击设计区的作业树,则其全部程序语句都将显示于编码区。点击某个作业的某区域,则会显该区域的程序语句,而且可以编辑修改之。由此可见,作业树不仅可读性好,而且便于修改维护。

   5) 理论性

   作业树与N-S图和PAD图之间最重要的区别是在理论价值上。如前所述,作业树的设计原理是基于结果倒推法,形成了Tq模型,符合分治法的设计原理。己经证明,作业树是表示问题求解算法的通用模型,任何问题的求解算法都可以用作业树来表示。致于N-S图和PAD图,因为他们没有规则的节点定义,更没有类似于Tq型态树的基本模型,所以无法从理论上讨论他们的适用性。

   实际上,作业树的理论价值还不止本文所涉及的。譬如,作业树还可以作为算法时间复杂度的分析模型。

   6) 系统性

   后面将会看到,作业树并非是孤立的程序设计工具,它是树型软件的一级结构树。没有作业树的严格定义,比作业范畴高一级的任务程序模块就无法定义。N-S图和PAD图都是程序设计工具,但没有与之配套的上级模块的结构设计方法,也就不好讨论其系统性。

   通过上述各方面的比较可以看出,作业树继承了N-S图和PAD图分层嵌套的优点,规范出了“作业级模块”,构造出了“初始型态树”和“Tq型态树”,进而采用结果倒推法Tq递归地进行设计。作业树是规范、成熟、通用的算法表示工具。

 

6.6 结束语

    从博文《冒泡排序程序的结构化设计》开始,笔者连续发表了《解 一元二次方程程序的结构化设计》、《常用二分查找程序的作业 树》、 《底2分化查找程序的作业树》、《作业树设计原理》和《作业树通 性证明》等6篇文章,内容都是关于作业树的。关于作业树的基本概念是在《冒泡排序程序的结构化设计》中给出的,约占该文篇幅的半。为了引出作业树的概念,该文的另一半篇幅实际是作业树设计 的第一个实例。接下来的3篇文章也都是关于作业树的设计实例。第56篇文章是从理论上对作业树的探讨。所以说,涉及作业树基本概念的内容只有半篇文章,约4000个字。弄懂了这半篇文章,也就可以设计作业树了。当然,全部6篇文章都看过,且进行过推敲与研判,对作业树的设计与研究就会更加驾熟就轻。

 

转载于:https://my.oschina.net/treesoft/blog/76319

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值