关于列车长的烦恼一题的思考

nencc 2011-05-09 07:38:57
关于列车长的烦恼问题前几天有人给发我了这样的代码,计算列车长的烦恼问题。此代码可以正常运行,且计算正确,代码非常短。
int main()
{
scanf("%d",&cases);
while(cases--)
{ scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&a[i]);
top=0;p=1;aa=1;stack[0]=-1;
while(p<n+1)
{
stack[++top]=p;p++;
while(stack[top]==a[aa]) { top--;aa++; } }
if(top==0) printf("Yes\n");
else printf("No\n"); }
return 0;
}
对代码分析后,初步结论:
一、代码短小原因
1.未构造类作为栈,而是只用数组stack和下表top进行操作,其实一个简单的栈也正是包含这两个因素。这样会单单是栈就会减少10行左右的代码。但是,这样的设计并不影响本质,即:自己构造一个完备的栈类丝毫不必直接使用数组会差,故并不推荐直接数组。直接使用数组在问题简单的情况下是可以的,但是问题复杂后,直接使用数组就不再那么有效。起码会让人觉得很累。(分析结果:不推荐此方法)
2.在判断分支时不够全面详细,虽然代码可以正确完成任务,但由于判断分支存在缺漏,会导致程序判断效率不高。代码短效率反而不高?是的,因为缺少了判断分支,某些情况下没有及时得出结果,而是简单的去判断下一个。后面我将画出此代码的流程图参考。(分析结果:简化了判断分支,代码短小但导致了效率的降低)
3.部分代码将多行代码写到一行中,看上去比实际的更短。(分析结果:不推荐此方法)
4.部分变量名用简单的a,p,aa,这种无确切含义的短名字,使代码看上去比实际的更短。(分析结果:不推荐此方法)
二、此代码核心算法与结构图
第一步:车厢进栈(因为是首节车厢,栈为空,除了进栈外别无选择)
第二步:比对栈顶车厢是否同输出序列车厢相符,若相符则出栈,比对序列车厢下一个
第三步: 继续进行第二步,直到出现不相等情况。
第四步:出现不相等时,回到第一步,右边车厢进栈(直到超出输入的车厢总数目)
第五步:判断栈内是否为空,为空则正确,不为空说明出错。
归纳一句话,比对是否相等,若相等则出栈,若不等则进栈。
因为栈来说,要么进栈要么出栈。车厢来说要么进来,要么出去。所以程序逻辑认为,如果比对不相符,那么一定需要进栈,如果相符那么出栈。这是正常的情况确实这样。但如果输出序列是错误的呢?
比如大家直到312是个不可能的序列,按照以上逻辑,一开始比对数字是3,
1:进栈。 栈内数据:1
2:比对,3!=1,继续进栈。栈内数据:1,2
3:比对,3!=2,继续进栈。栈内数据:1,2,3
4:比对,3==3,出栈, 栈内数据:1,2
5:比对1!=2(因为输出序列第一个3已经匹配,继续比对输出序列下一个1,栈顶为2,比对不符) ,进栈, 因为总数是3,已无车厢进栈。结束判断。
6:判断栈是否为空,栈内元素为1,2,显然不为空,故判断出此序列是错误的。
int a[110],stack[110],cases,n,i,p,top,aa; 三、程序存在问题举例:由于312是不可能序列,若输出序列为:3,1,2,4,5,6,7,8,9.。。。。。。
一个比较长的序列,假设有100节车厢,输出序列是前面是3,1,2,后面都是按序拍好的(或者随意排的)。
我们期望是当看到312,时就已经能够判断出错,而不必再去判断后面序列,及时退出给出结果。而按照此简洁算法逻辑执行如下:
1:进栈。 栈内数据:1
2:比对,3!=1,继续进栈。栈内数据:1,2
3:比对,3!=2,继续进栈。栈内数据:1,2,3
4:比对,3==3,出栈, 栈内数据:1,2
5:比对1!=2(因为输出序列第一个3已经匹配,继续比对输出序列下一个1,栈顶为2,比对不符) ,进栈, 栈内数据:1,2,4
6:继续比对1!=4,进栈, 栈内数据:1,2,4,5
7:继续比对1!=5,进栈, 栈内数据:1,2,4,5,6
8:继续比对1!=6,进栈, 栈内数据:1,2,4,5,6
9:继续比对1!=7,进栈, 栈内数据:1,2,4,5,6,7
。。。。。。。
一直比对到100,最后栈内数据是:1,2,4,5,6,7.。。。。。。100
程序最后判断栈是否为空,结果栈内确实很满,此时才给出不匹配的结论。。。。。
其实我们是期望在第5处就能及时发现不匹配,而不用再往下进行了。能够及时退出的算法即流程图上次我已经发给你了,可以作为参考。就是多出2个判断分支。这里只做相等的判断,在那里我还做了大于,小于的情况分别进行判断,能够最快的得出结论。
...全文
170 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
zz5246653 2011-05-12
  • 打赏
  • 举报
回复
好详细啊~~~~~~~~
nencc 2011-05-09
  • 打赏
  • 举报
回复
问题分析:
右边待进入的车厢一定是按序号排列好的,例如:1 2 3;
左边给出的输出结果,是经过一系列入栈出栈的结果,问此结果是否可能,例如3 1 2;

解决方法:
程序可通过反向推理来验证结果是否能由入栈出栈的到。
例如输入3 1 2,
第一个出来的车厢是3,说明,前面的车厢都已进栈,进栈顺序,1 2;
第二个出来的车厢是1,说明,需要出栈比对,由于最后进栈是2,出栈比对不匹配,故此结果是不可能结果。(如果比对成功,则继续比对)

设右面等待进入的车厢为有序入栈序列,1,2,3,4,5,6,7,8,9,10.。。。。
可用一个整数表述,初始值为1,每次需要入栈,此数字加1,想象后面有无数节车厢等待入栈(如果需要),这样就不存在入栈车厢数目问题,只通过左边出站后的数目判断。对于程序来说,这个数目是由键盘输入确定的。

左边的输出序列需要一个数组保存。
比对的最大数目(最大车厢)需要一个变量保存。
nencc 2011-05-09
  • 打赏
  • 举报
回复

3,882

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧