分享

问答集锦:怎样提高程序效率 之“先排序,后遍历”

 L罗乐 2016-10-06

大家好!国庆节继续快乐!在前几天发布的最新补充练习《循环技巧之动态汇总》中,我给参考答案之外,又给大家提出了一个深入的思考:怎样进一步提高效率?之后有很多同学已经开始尝试,并通过各种渠道与我交流这个问题。那么今天,我就抛砖引玉,为大家介绍一种常用的思路:“先排序,后遍历”

 

以我们这个作业为例(如下图),我们给出的参考答案的思路是:先做一个循环扫描左侧表格的每一行;每找到一行,就记住它的公司名,然后再做一个循环,在右侧表格中查找该公司名,直到发现该名称或走到空白行(即不存在该名称)为止。这是一个典型的双重循环,执行次数可以达到两表行数的乘积的水平。



在官网论坛上,我在点评同学作业时提到:假如这些数据已经排好序,如下图所示,那么我们的程序是否会简单一些呢?(为方便在微信中显示,下图案例删除了一些数据行)



我们分析一下:在这种情况下,我们还是先做一个循环扫描左表,不过与之前不同的是,从第3行扫描到第13行时,只可能遇到同一个公司“大华”,不可能遇到其他公司名;而从第14行开始,则永远不可能再遇到“大华”,因为数据是排好序显示的。


利用这个特点,我们可以编写一个新的程序:


首先,我们让右表第3行H列公司名等于左表第三行B列,即左表中出现的第一个公司名;


然后指定一个变量p=3,代表右表的这一行。然后,我们还是做一个循环扫描左表;每找到一行,就看这一行的名字与右表中第p行H列是否相同:

如果相同,与以前一样,就将其增一;

如果不同,说明我们在左边遇到了一个新的公司名,同时也就意味着,右表当前第p行的这个公司名再也不会遇到了(参见上一段对“大华”的解释)。于是,我们就将p增加一,让它指向右表的下一个空白行,然后让第p行H列等于新发现的公司名。


就这样循环执行下来,一样可以完成任务。而且,我们只使用了一层循环!整个程序的执行效率,不再是两表数据量的乘积水平,而只是左表数据量的水平!这个思路写成代码就是下面的参考答案:



不过这里还有一个问题,就是怎样先对数据进行排序呢?学过编程的同学可能马上会想起期末考试时被各种排序算法问题折磨的日子了。的确,排序本身也是一个非常耗时的操作,而且有非常多的算法供选择。不过在Excel VBA中,你完全不用为此担心!因为我们可以直接使用Excel工具栏上自带的“数据”—“排序”功能,速度超快而且操作简单。如果你想在程序中自动实现这个功能,只需要用“录制宏”(《基础篇》第9回)把排序代码录制下来,稍作改动以便能够根据你的程序灵活指定行/列,就可以了。这个任务就留给大家自己去思考。


最后再说一句,大家千万不要小看了本文这种思路的重要性!“先排序、后遍历”可以说是非常基础的算法思想,特别是当数据量非常庞大,它给你节省的时间可以是十个小时以上。当年杨老师在银行工作时,就曾经遇到过这样的任务:每个月都要把集团员工名单与上一个月的名单进行比对,筛选出人员变化。这个任务看似简单,一个双循环就轻易搞定,但是由于每个名单都有几十万左右的姓名,所以程序跑起来一天都停不下来。有同事将它导入Access数据库,并且加了索引,然后使用SQL比对,却也没有号多少。不过我们只在VBA程序中先使用Excel数据排序,然后只一个循环做动态比对,复杂度从O(n^2)降到O(n),几十分钟就轻松搞定!所以请大家还是认真琢磨一下这个思路,说不定哪天就能用上。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多