新版代码地址:https://git.coding.net/clairewyd/wf.git
ptime运行结果:
瓶颈预测:
根据代码猜测瓶颈应该在排序算法上,猜测此处为瓶颈主要是因为程序采用的是hashtable来存储单词,之后要根据hash表中键所对应的值进行排序,将键和值分放在两个数组中,以相同的索引为媒介,之后要同时对两个数组进行操作,故而需要操作的数据很多,可能成为程序瓶颈。在编程初始时使用的是冒泡排序,后来考虑到效率问题程序改为使用排序算法中较快的快速排序算法,时间复杂度从O(n^2)提高到O(nlogn)。
排序算法片段:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/// <summary> /// 快速排序算法 /// </summary> /// <param name="valueArray">单词对应的词频数数组</param> /// <param name="keyArray">存放单词数组</param> /// <param name="v1">左索引</param> /// <param name="v2">右索引</param> private void QuickSort(int[] valueArray, string[] keyArray, int v1, int v2) { if (v1 < v2) { int index2 = Division(valueArray, keyArray, v1, v2); QuickSort(valueArray, keyArray, index2 + 1, v2); QuickSort(valueArray, keyArray, v1, index2 - 1); } } public int Division(int[] valueArray, string[] keyArray, int v1, int v2) { while (v1 < v2) { int num = valueArray[v1]; string num2 = keyArray[v1]; if (num < valueArray[v1 + 1]) { valueArray[v1] = valueArray[v1 + 1]; valueArray[v1 + 1] = num; keyArray[v1] = keyArray[v1 + 1]; keyArray[v1 + 1] = num2; v1++; } else { int temp = valueArray[v2]; valueArray[v2] = valueArray[v1 + 1]; valueArray[v1 + 1] = temp; string temp2 = keyArray[v2]; keyArray[v2] = keyArray[v1 + 1]; keyArray[v1 + 1] = temp2; v2--; } } //Console.WriteLine("----------\n"); return v1; }
以下是性能测试热路径截图以及题目中要求的最耗费时间的三个函数的代码位置。可以看到瓶颈并不是猜想中的排序函数,而是用foreach遍历MatchCollection消耗时间最多,其次是判断hash表中是否存在某个单词,以及在hash表已经包含某个单词时将object转换成int型+1并记录词频。
这几个函数都已经是在考虑效率的情况下才使用的,看到了有的同学使用了Dictionary,但字典与hash表相似,因为dictionary支持泛型所以可以不用做在上述中第三耗时的类型转换,但是字典是聚合存储,hash表是散列存储,而且作业中的key是字符型,在编程时如果有大量无规律数据的随机检索也是使用hash表较多,故而在作业要求中即使改成字典也应无法很大地提高效率(因为上周的代码不符合要求需重写所以实在没时间去亲自检验,只能理论分析了),也因本人在c#方面编程能力不足,目前并没有找到更好的解决办法。
以上是运行原始代码的结果,根据老师要求更改了程序,通过命令行参数进行执行,但是更改完的程序不知为何不能进行效能分析。以下是截图证据:
之后也改了启动命令:
又改了命令行参数
但是不知为何在这里输入的“ -s < war_and_peace.txt" 只识别了"-s",后边表示重定向的命令并没有被ide识别,运行之后执行的是功能1.
故而新版代码未能进行效能分析,但是因为新版代码只更改了主函数,工具类并没有改变,所以使用原始代码进行的效能分析也可以在很大程度上反应新版代码的效能。
最终版代码运行时间: