自顶向下,逐步求精

这里写图片描述

自顶向下

这里写图片描述
自顶向下(top-down)的分析算法通过在最左推导中描述出各个步骤来分析记号串输入。

自顶向下的意义

将复杂的大问题分解为相对简单的小问题,找出每个问题的关键、重点所在,然后用精确的思维定性、定量地去描述问题。其核心本质是”分解”。
之所以称这样的算法为自顶向下是由于分析树隐含的编号是一个前序编号,而且其顺序是由根到叶自顶向下的分析程序有两类:回溯分析程序(backtracking parser)和预测分析程序(predictive parser)。预测分析程序试图利用一个或多个先行记号来预测出输入串中的下一个构造,而回溯分析程序则试着分析其他可能的输入,当一种可能失败时就要求输入中备份任意数量的字符。虽然回溯分析程序比预测分析程序强大许多,但它们都非常慢,一般都在指数的数量级上,所以对于实际的编译器并不合适。
递归下降程序分析和LL(1)分析一般地都要求计算先行集合,它们分别称作First集合和Follow集合。由于无需显式地构造出这些集合就可以构造出简单的自顶向下的分析程序。
您可以自下而上设计一个装配体,或自上而下进行设计,或两种方法结合使用。

例子

例 验证“哥德巴赫猜想”
求解

第一步 提出问题: 验证哥德巴赫猜想

第二步 设一上限数M,验证从4到M的所有偶数是否能被 分解为两个素数之和。
1. 定义一个变量X,初值为4。
2. 每次令其加2,并验证X能否 被分解为两个素数之和,直到 X不小于M为止。

第三步 如何验证X是否能被分解为两个素数之和。
1. 从P=2开始;
2. 判别X—P是否仍为素数:
3. 若是,打印该偶数的分解式。
4. 否则,换更大的素数,再继续执行2.。如此循环,直到用于检测的素数大X/2且X 与其之差仍不是素数,则打印“哥德巴赫猜想”不成立。

第四步 查找下一个素数。
(1)当前素数P加1
(2)判别P是否是素数;
(3)若是素数,返回P;
(4)否则,P加1,继续执行( 2)。
哥德巴赫猜想是数论中的一个著名难题, 是由法国数学爱好者克里斯蒂安·哥德巴赫于1742年在给著名数学家欧拉的一封信中提出的。
“哥德巴赫猜想”可以表述为:任何一个大于等于4的偶数均可以表示为两个素数之和。
尽管这个问题看来如此简明清晰, 但二百多年来, 虽有无数数学家为其呕心沥血、绞尽脑汁, 却始终无人能够证明或者证伪这个猜想 。

逐步求精

这里写图片描述
将现实问题经过几次抽象(细化)处理,最后到求解域中只是一些简单的算法描述和算法实现问题。即将系统功能按层次进行分解,每一层不断将功能细化,到最后一层都是功能单一、简单易实现的模块。求解过程可以划分为若干个阶段,在不同阶段采用不同的工具来描述问题。在每个阶段有不同的规则和标准,产生出不同阶段的文档资料。

例子

/*[例]要求用筛选法求100以内的素数。筛选法就是从2到100中去掉2,3,„,9,10的倍数,省下的就是100以内的素数。  为了解决这个问题,我们可以先按程序功能写出一个框架。*/
 Main( ){    建立2100的数组A[  ],其中A[i]=i;„„„„„„1    建立210的素数表B[  ],其中存放210以内的素数;„„2   若A[i]=i是B[  ]中任一数的倍数,则剔除A[i];„„3   输出A[  ]中所没有被剔除的数;                   4 }  上述框架中的每一个加工语句都可以进一步细化成一个循环语句。 Main( ){    /*建立2到100的数组A[  ],其中A[i]=i;*/„„„„1   for(i=2;i<=100;i++)     A[i]=i;    /*建立2到10的素数表B[  ],其中存放2到10以内的素数;*/2     B[1]=1;  B[2]=3;  B[3]=5;  B[4]=7;    /*若A[i]=i是B[  ]中任一数的倍数,则剔除A[i];*/3   for(j=1;j<=4;j++)                                检查A[  ]所有的数能否被B[j]整除并将能被整除的数从A[  ]中剔除;   3.1   /*输出A[  ]中所没有被剔除的数;*/                4   for(i=2;i<=100;i++)      若A[i]没有被剔除,则输出之                    4.1 }  下面继续对3.14.1细化下去,直到最后每一个语句都能直接用程序设计语言来表示为止。 Main( ){    /*建立2到100的数组A[  ],其中A[i]=i;*/   for(i=2;i<=100;i++)     A[i]=i;    /*建立2到10的素数表B[  ],其中存放2到10以内的素数;   B[1]=1;  B[2]=3;  B[3]=5;  B[4]=7;    /*若A[i]=i是B[  ]中任一数的倍数,则剔除A[i];*/   for(j=1;j<=4;j++)                              检查A[  ]所有的数能否被B[j]整除并将能被整除的数从A[  ]中剔除;  for(i=2;i<=100;i++)    if(A[i]/ B[j]* B[j]= = A[i])     A[i]=0    /*输出A[  ]中所没有被剔除的数;*/   for(i=2;i<=100;i++)      /*若A[i]没有被剔除,则输出之*/     if(A[i]!=0)        printf(“A[%d]=%d”,i,A[i]) } 

实例:洗衣机的运作分析

Water_in_switch(open) Set v to get_water_volunm If v>=v_expected then  Water_in_switch(close) While time != time_counter  motor_run(right)  motor_run(stop)  motor_run(left)  motor_run(stop) endwhile while water != 0 water_out_switch(open) endwhile water_out_switch(close) halt(success) 

Water_in_switch(open)
Set v to get_water_volunm
If v>=v_expected
While time != time_counter
motor_run(right)
motor_run(stop)
motor_run(left)
motor_run(stop)
endwhile while water != 0
water_out_switch(open)
endwhile
water_out_switch(close)
halt(success)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值