题目集5~7单部电梯调度程序总结

  1. 前言:

        在题目集5中的单部电梯调度程序难度中等,难度主要体现在对电梯运行逻辑的理解,主要考察的知识点是类与对象。题目集6中的单部电梯调度程序在前面题目的基础上增加了一些要求,必须包含电梯类、乘客请求类、队列类以及控制类,比前一题更加考验我对类与对象的知识点的理解,在电梯运行上增加了考虑不合理请求的内容,难度比第一题大,难度较大。题目集7中的单部电梯调度程序难度与题目集6相差不大,难度较大。第三题电梯改变了外队列的输入格式,并加入乘客类(Passenger),取消了乘客请求类,让设计更加合理。

   2.设计与分析:

        (1)第一次电梯源码分析:

        本次电梯我按照题目设计了一个电梯类,因此该类包括多个方法与许多成员变量,没有遵循单一职责原则。首先包括int类型的camx(最高层),cmin(最低层),cdq(当前层),并且把电梯方向也设计成int类型,int fx,用-1表示方向向下,用1表示方向向上,用0表示方向改变的中间状态,方向可以为0目的是方便后面电梯运行逻辑的设计,状态在本次题目中并未用上,但我把它设计成int zt(状态)。然后是int类型的数组,int[] ndl=new int[200](内对列),int[] wdl=new int[200](外对列),int[] wdlfx=new int[200](外对列方向)。String[] sch = {"DOWN", "UP", "UP"}将来输出时用来表式方向。构造方法只有一个,输入最大层和最小层,当前层cdq=1,方向fx=1因为电梯最开始默认在最低层1,所以开始方向必为向上,状态zt=0。然后是传入内外队列数据的函数setndl和setwdl,setndl需要传入nqqc需要去的楼层和ni传入的第几个数据,用来ni依次把nqqc放入数组。setwdl需要传入wqqc乘客所在楼层和wfx乘梯方向和wi作用同ni。最后是电梯运行最重要的方法dtyx(电梯运行),它来处理请求并且按格式输出,包含复杂的逻辑,首先int i,j,每处理一个内请求就i++,每处理一个外请求就j++,然后包括三个while大循环,第一个循环进行的条件是ndl[i]和wdl[j]都不为0,第二个循环的条件是wdl[j]不为0,第三个循环的条件是ndl[i]不为0。第一个循环需要比较内外对列离当前层的距离,因此两个对列中的任何一个都不能为0,剩下的两个循环则是用来处理剩下的一个对列。第一个循环首先用if判断现在方向是不是为0,如果为0则判断内外对列的第一个请求哪个离cdq当前层近,其中用了绝对值Math.abs来计算,然后哪个更近就用当前层cdq减去它,判断方向是向上还是下,然后加入小循环,cdq=cdq+fx因为方向向上fx就等于1反之等于-1,这样就可以让cdq一层一层向目的层运行,并且在while中加入输出信息这条代码,符合了题目输出要求,循环进行条件是cdq!=wdl,循环停止后输出Open Door等内容,然后else if如果fx=1,则判断ndl[i]是否小于cdq并且wdlfx[j]是否为-1,如果是则fx=0,这样就回到第一个if了,化简了代码,如果wdlfx[j]等于1并且ndl[i]>cdq,则fx=0回到第一个if,如果不是前面两种情况就表明有一个对列是和当前方向相同,根据题目意思则去与当前方向相同的层,else则是fx=-1的情况,与方向向上情况逻辑相同,到此第一个大while循环结束。第二个循环就是只处理剩下的外对列,按题目意思就是只要按顺序处理即可,即判断方向是-1还是1后用while循环cdq=cdq+1并输出信息即可,第三个循环与第二个循环相差不大,逻辑相同。

        然后是main方法,main方法的主要内容就是对输入的数据进行处理,因为内请求输入格式是<楼层数>,外请求格式是<乘客所在楼层数,乘梯方向>,并且输入的每个请求都是独占一行,因此我用String s=sc.nextLine()来输入一行,然后计算了字符串s的长度,如果是外请求,那就要包含一个逗号并且包含一个up或者down,那这样字符串s的长度就必定大于等于6,内请求不包含这些内容,长度就更短,我以此来判断nextLine是内还是外请求,如果是内请求,则用一个字符串str1接收s. substring(1,leng-1),因为格式是确定的,这样就能得到字符串类型的内请求楼层,然后用Integer.parseInt(str1)把它转换成int类型,外请求则需要先用s.indexOf("U")查找是否包含U,来判断外乘客请求方向是上还是下,把<乘客所在楼层数,乘梯方向>转换成数据方式与内请求转换方法相似,一直输入直到输入end为止。

  • (2)第二次电梯源码分析:

        第二次的代码是在第一次的基础是进行修改后得到的,在本次电梯中,我的电梯运行逻辑部分并没有改变,输入时处理数据也没有改变,大部分内容都保留下来,只是将他们拆分到多个类里,我把方法dtyx(电梯运行)代码从Dt类转移到了Controller类,把setndl和setwdl拆出Dt类,分别成为inRequest和exRequest类,并把main中的处理<楼层数>分别放在了它们里面。我在这题增加的内容是:判断输入的数据是否是相同的多余输入以及乘客请求楼层数有误。我把判断的代码放在main函数里了,新String sjc来存放前一行内容,然后判断sjc和当前s是否相等,如果相等就跳过当前s,s=sc.nextLine(),但这样做有一点问题,在踩坑心得和改进建议中细说。

  • (3)第三次电梯源码分析:

        第三次改变了输入方式,把电梯外乘客请求格式改成<请求源楼层,请求目的楼层>了,我在第三次电梯转换外请求的方法里加入了:请求目的楼层-请求源楼层,来判断方向是up还是down,这里没读懂题目意思,一次性把请求目的楼层全部加入到请求内部队列(加到队尾)里了,导致错误,我的运行部分逻辑没有改变,内外请求对列也没变。按题目要求加入乘客类(Passenger),取消乘客请求类。

        3.采坑心得:

        (1)第一次电梯我在电梯运行的逻辑上有许多错误,比如在运行时当处理了一个外请求后,我的方向没有改成外对列的乘梯方向。我的电梯的方向初始化为0,导致输出第一行时错误,输出的方向错误。每次移动一个楼层,需要检查是否有需要停靠的请求,我开始没有考虑外请求方向的问题,简单的看楼层是否相同,导致轻易的减少了外请求,导致输出错误。

        (2)第一次电梯没有看清,简单的用了s.equals(),但是需要不分大小写的end,所以非零返回。

  • (3)第二次电梯需要检查请求是否合理,在这里我发现我的最高层和最低层输入反了,导致没有输出。
  • (4)第二次电梯在main函数中判断是否输入时前一次输入和后一次输入是否相同,如果相同这跳过,但是如果输入<3> <5,DOWN> <3> <5,DOWN> <3>,就会导致不会把<3><3><3>过滤为<3>,没有考虑到所有情况。
  • (5)第三次电梯中一次性把请求目的楼层全部加入到请求内部队列(加到队尾)里了,没有符合题目当电梯处理该请求之后(该请求出队)加入到请求内部队列(加到队尾),这样就会导致运行时本应该在外请求处理完后才能处理的内请求更早被运行,导致去楼层的顺序错误。
  • (6)第三次电梯为了符合题目要求,我在输入完内部队列后,在末尾再输入一个去-1层的请求,再把外对列的请求目的楼层加入到请求内部队列。在电梯运行时,要外对列运行完才能运行内对列-1后面的请求,这里还是没有考虑正确,没有找到正确办法。

        4.改进建议:

        第一次电梯把大量代码放在一个类中,让代码可读性很差,电梯类职责过多的问题,要分成多个类,类设计要求遵循单一职责原则。

        第二次电梯应该在对列类中忽略相同的多余输入,不应该放在main函数中,这样才能正确过滤掉相同输入,不会因为内外对列相同请求混合在一起后无法过滤导致错误。

        第三次电梯要根据题目意思,每处理应该外部请求后在把请求加入内对列最后,应该把这部分代码放在电梯运行函数里面,才能准确的做到电梯处理该请求之后,将<请求        源楼层,请求目的楼层>中的请求目的楼层加入到请求内部队列。

        5.总结:

        通过完成这三题电梯题目,我掌握了通过类之间的协作来解决问题,将实际问题抽象为类和对象,在处理复杂逻辑和调试代码方面积累了丰富的经验,进一步理解了面向对象的设计原则和思想。

        我需要进一步学习类的设计,如第一题我自己设计的类十分不合理,后续题目也是按照题目给出的类图来设计的。还有电梯运行部分的代码太复杂,没有找到更简单的逻辑以及方法,导致有许多if和else还有多个while循环,并且在多个while循环中还存在许多重复代码,没有写出方法来化简while循环。

建议是多给出一些输入样例,首先是在解释电梯运行过程时结合多个例子,清晰呈现出题目的运行逻辑,要求等,防止错误理解题目意思,防止题目的逻辑表达片面,误导理解,其次是方便及时找出逻辑错误。

posted @ 2025-04-20 19:35  3770351  阅读(53)  评论(0)    收藏  举报