赞。当然可以啦。在这个问题下:http://coding.imooc.com/learn/questiondetail/3044.html 我的第三点就是这个思路。
其实我们也可以很容易的做一次实验。以下代码是我针对100万的数据,在我的计算机上的实验结果。其中Merge Sort 1使用在merge时申请栈空间;Merge Sort2使用在merge外面开辟aux数组,再将aux数组传递给merge。两个MergeSort均未使用其他优化。
Merge Sort 1 : 0.451496 s
Merge Sort 2 : 0.444103 s
可以看到,Merge Sort 2确实快了。但是快的非常不明显。
为了避免是一次数据产生的偏差,我们可以使用多次测试取平均值的方式,来获得更加精准的具有统计意义的结果。下面的结果是针对两种方式,100万的数据量,各运行100次后,取平均值的时间。(这种方式其实在看算法的效果的时候非常常用!)
Merge Sort 1 Average Run Time: 0.394418 s
Merge Sort 2 Average Run Time: 0.361739 s
不要问我为什么一次实验运行结果是0.4+;而另一次实验是0.3+,我也不知道。现代计算机运行的过程中,有太多的干扰因素是我们无法排除的。但大体上,我们的算法是稳定在一个时间范围里的。(对100万的数据进行排序,在我的计算机上,在0.5s的范围内),同时,更重要的是,我们可以观察到趋势,将aux放在外面传给merge的归并排序确实会更快一些。
但是,你也发现了,其实快的并不多。我们可以简单分析一下。
1)将aux数组的空间开辟放在外面,虽然减少了在merge中反复开空间的消耗,但同时增加了传参的消耗。(不过堆内存的操作比传参耗费要更大)
2)现代编译器针对一些代码,会进行一些优化。解释器也是如此。代码运行时,对内存的使用也可能有内部优化。
所以,这步优化效果并不明显。不过我们还是可以清楚地看到,这样做确实是有效的:)
在课程中,由于aux只在merge的过程中使用,所以我就把aux的声明放在merge里了,便于理解。这样,每一个模块儿的任务很清晰,所有的变量,在哪里使用,就在哪里声明。但是,如果透彻理解了MergeSort的话,完全可以这样做。尤其是将MergeSort包装成类的时候,aux就可以大摇大摆的变成一个私有的成员变量啦。这样,就不需要在方法间传递这个参数了:)
我为了回答这个问题,实验的代码,可以参见:https://github.com/liuyubobobo/Play-with-Algorithms/tree/master/03-Sorting-Advance/Course%20Code%20(C%2B%2B)/MergeSortImplementationComparision