您的位置:首页 > 其它

简述“自顶向下,逐步求精”——面向过程程序设计方法

2017-11-28 00:09 701 查看

引入

 所谓“自顶向下,逐步求精”的程序设计方法,网络上有着如下的说法,一者是百度百科所述,另一者则为维基百科的说法。

自顶向下设计 :一种逐步求精的设计程序的过程和方法。对要完成的任务进行分解,先对最高层次中的问题进行定义、设计、编程和测试,而将其中未解决的问题作为一个子任务放到下一层次中去解决。这样逐层、逐个地进行定义、设计、编程和测试,直到所有层次上的问题均由实用程序来解决,就能设计出具有层次结构的程序。

——百度百科

In computer science, divide and conquer is an algorithm design paradigm based on multi-branched recursion. A divide and conquer algorithm works by recursively breaking down a problem into two or more sub-problems of the same or related type, until these become simple enough to be solved directly. The solutions to the sub-problems are then combined to give a solution to the original problem.

——Wikipedia

个人看法

 要说到“自顶向下”,那么肯定是有着一个顶部的存在——就是一个或若干个复杂的大的问题。那么将这复杂、大的问题划分为小问题,找出问题的关键、重点所在,然后用精确的思维定性、定量地去描述问题,就是“自顶向下”方法的思路和体现。

  至于“逐步求精”,那就是将现实世界的问题经抽象转化为逻辑空间或求解空间的问题。复杂问题经抽象化处理变为相对比较简单的问题。经若干步抽象(精化)处理,最后到求解域中只是比较简单的编程问题。

 其中,具体可分为以下几钟不同的抽象处理方式:

①顺序结构

②选择结构

③循环结构

 而其中最复杂的要数循环结构,但这种方法却是解决问题较为有效的一种方法,比如说它可以解决洗衣机运行的问题,而今日我就将用这种“自顶向下,逐步求精”的方法实现普通洗衣机运行程序的伪代码。

 不过在这之前,我得先用一个简单的例子来熟悉熟悉这一种方法。

例1:杨辉三角

例1:输入一个数字n(1<=n<=10), 不在范围内的n输出“Out Of Range.\n” 输出杨辉三角的前n行

 为什么我会选择杨辉三角来充当本文的第一个例子而不选择简单的1+2+3+…+n这种问题来充当例子呢?

&esmp;很简单,那种1加到100的问题逼格不够,一看就是拿来敷衍的。(吐槽一发)

 那么,这个杨辉三角怎么样才能够用代码实现呢?

 方法有很多,因为这个数阵这么多年来早已经被人类给摸得七七八八了:

规律:



从上图可看出杨辉三角的几个显著特征:

1. 每行数值左右对称,且均为正整数。

2. 行数递增时,列数亦递增。

3. 除斜边上的1外,其余数值均等于其肩部两数之和。


①先提一种较为直观的方法, 杨辉三角与二项式定理有密切关系,即杨辉三角的第n行(n=0…MAX_ROW)对应二项式(a+b)n展开(Binomial Expansion)的系数集合

。例如,第二行的数值1-2-1为幂指数为2的二项式(a+b)^2展开形式a^2 + 2ab + b^2的系数,即


组合后得到:



故 直接利用特征3求解杨辉值,即第i行的第j个数等于第i-1行的第j-1个数与第j个数之和,用二维数组形式表达即为a[i][j] = a[i-1][j-1] + a[i-1][j],通俗易懂简洁。

代码实现:

1 void BasicYangHui(void)
2 {
3     int dwRow = 0, dwCol = 0, aTriVal[MAX_ROW][MAX_COL] = {{0}};
4
5     for(dwRow = 0; dwRow < MAX_ROW; dwRow++)
6     {
7         aTriVal[dwRow][0] = aTriVal[dwRow][dwRow] = 1;  //若为i行0或i列,则i行j列杨辉值为1
8     }
9
10     for(dwRow = 2; dwRow < MAX_ROW; dwRow++)
11     {
12         for(dwCol = 1; dwCol < dwRow; dwCol++) //否则,i行j列杨辉值为i-1行中第j-1列与第j列值之和
13             aTriVal[dwRow][dwCol] = aTriVal[dwRow-1][dwCol-1] + aTriVal[dwRow-1][dwCol];
14     }
15
16     //输出杨辉三角值
17     for(dwRow = 0; dwRow < MAX_ROW; dwRow++)
18     {
19         for(dwCol = 0; dwCol <= dwRow; dwCol++)
20         {
21             printf("%5d", aTriVal[dwRow][dwCol]);
22         }
23         printf("\n");
24     }
25 }


②我要是连数组都懒得用呢,好的,也可以,这就需要继续找规律咯(我贴出代码,至于规律,则是已深在其中)。

int main()
{
int s = 1, h;                    // 数值和高度
int i, j;                        // 循环计数
scanf("%d", &h);                 // 输入层数
printf("1\n");                   // 输出第一个 1
for (i = 2; i <= h; s = 1, i++)         // 行数 i 从 2 到层高
{
printf("1 ");                // 第一个 1
for (j = 1; j <= i - 2; j++) // 列位置 j 绕过第一个直接开始循环
//printf("%d ", (s = (i - j) / j * s));
printf("%d ", (s = (i - j) * s / j));
printf("1\n");               // 最后一个 1,换行
}
getchar();                       // 暂停等待
return 0;
}


如图:



这就轻松完成了打出杨辉三角的代码部分。

等下,这题目不是还有个范围吗?好的,这就是此文要讲述的自顶向下,逐步求精的方法。

 刚才所列的是杨辉三角打印的原理代码部分,虽然看似已经解决了这个题目,但不要忘了,这仅仅只是题目的一部分,距离真正完成还是差了并不止一点哦。

 回观题目,【不在范围内的n输出“Out Of Range.\n”】,这一句,是与代码平行乃至更强的条件限制部分,因此在完成该任务的开始,就应分好层次,若n不在这个范围,就直接跳出而打印“Out Of Range.\n”咯。(跳槽一下:反正也就那么几个不同的数,实在想不到规律的还不如直接打表哈哈!!!)

至此,任务完成咯。

例2:洗衣机



 洗衣机作为日常生活中极其重要的电器,其操作定然是便于人们使用的,而如何使得人们操作它而感到方便舒适,则是程序设计者的任务!

 若使用之前所述的“自顶向下,逐步求精”的方法,首先要做的,便是分析洗衣机所具有的功能,然后是这些功能操作所需要的过程,然后我们在分别对此以程序!

正常而言,一个洗衣机程序,不可缺少的必然有进水,洗涤(漂洗),排水,脱水等程序。

而将它们分别用代码实现,则又需要思考设计它们分别的实现方式,比如说,脱水的时间、进水的时间或量、以及洗涤时洗衣机滚轴的转动方式等等。而思考到这一层之后,接下来进行的便是使用最简单使实用的代码使之实现!!伪代码如下:

READ 用户选择模式

REPEAT   注水 UNTILL 水位=注水要求

REPEAT   浸泡 UNTILL 时间 = 时间要求

WHILE(电机启动时间>0)
{ REPEAT
电机左转3次
电机右转3次
时间-1单位
}
ENDWHILE

WHILE(水位!=0)
排水
ENDWHILE

FOR(脱水时间>0)
电机转动
脱水时间-1单位
ENDFOR
关闭电源


而设计完这些最基本的步骤,还需要的便是思考功能,比如说:快洗与普通洗的区别,再附以代码来实现之后组装在一次就完成此项目咯。

 本次对于程序设计方法原理的学习让我对未来软件设计充满了希望,毕竟,一般而言,同等条件下,一个有方法的人总比没有的要出色,是吧?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: