效能分析——词频统计1.1版

前言:在寻错及修改两天之后,发现之前的程序不能处理大文件的原因在于所写的排序部分,于是做了两件事:

第一是修改了所写的quick排序部分,现在可以处理大文件了;

第二是学习了http://www.blogjava.net/killme2008/archive/2010/09/08/quicksort_optimized.html 中写的关于快速排序算法的优化改进,也移植到了我的程序里试了试。

分别使用两种方法处理同一份文件,大小是1M,不同的词有17000,这个大小的文件之前是一处理就崩溃的,算是有所进步了。

方法一:

方法二:

方法二的代码:

void qsort7(struct fre_word *f, int p, int r)
{

	char x[word_size];
	int len = r - p + 1;
	if (p >= r)
		return;

	// 在数组大小小于7的情况下使用直接插入排序
	if (len< 7)
	{
		for (int i = p; i <= r; i++)
		{
			for (int j = i; j > p && f[j - 1].num > f[j].num; j--)
			{
				swapf(f, j, j - 1);
			}
		}
		return;
	}

	// 选择中数,与qsort6相同。

	int m = p + (len >> 1);
	if (len > 7)
	{
		int l = p;
		int n = r;
		if (len > 40)
		{
			int s = len / 8;
			int s2 = 2 * s;
			l = med3(f, l, l + s, l + s2);
			m = med3(f, m - s, m, m + s);
			n = med3(f, n - s2, n - s, n);
		}
		m = med3(f, l, m, n);
	}

	int v = f[m].num;
	strcpy(x, f[m].wd);

	// a,b进行左端扫描,c,d进行右端扫描
	int a = p, b = a, c = p + len - 1, d = c;
	while (true)
	{
		// 尝试找到大于pivot的元素
		while (b <= c && f[b].num <= v)
		{
			// 与pivot相同的交换到左端
			if (f[b].num == v)
				swapf(f, a++, b);
			b++;
		}
		// 尝试找到小于pivot的元素
		while (c >= b && f[c].num >= v)
		{
			// 与pivot相同的交换到右端
			if (f[c].num == v)
				swapf(f, c, d--);
			c--;
		}
		if (b > c)
			break;
		// 交换找到的元素
		swapf(f, b++, c--);
	}

	// 将相同的元素交换到中间
	int s, n = p + len;
	s = (a - p)>(b - a) ? (b - a) : (a - p);
	vecswap(f, p, b - s, s);
	s = (d - c)>(n - d - 1) ? (n - d - 1) : (d - c);
	vecswap(f, b, n - s, s);

	// 递归调用子序列
	if ((s = b - a) > 1)
		qsort7(f, p, s + p - 1);
	if ((s = d - c) > 1)
		qsort7(f, n - s, n - 1);

}

方法二特点是分情况进行排序,在需要排序的数组数量小于一个值的时候使用直接插入排序,大于的时候使用快速排序,在选取枢轴的时候也是用的是三数取中,可以避免快速排序的在选枢轴的弊端。

其中涉及到三个调用的函数:

swapf目的是交换两个结构体的数据。

void swapf(struct fre_word *f, int a, int b)//交换两个结构体内的数据
{
	int temp;
	char x[word_size];
	temp = f[b].num;
	strcpy(x, f[b].wd);
	f[b].num = f[a].num;
	strcpy(f[b].wd, f[a].wd);
	f[a].num = temp;
	strcpy(f[a].wd, x);
}

 vecswap目的是批量交换连续的结构体。

void vecswap(fre_word *f, int a, int b, int n)
{
	for (int i = 0; i < n; i++, a++, b++)
		swapf(f, a, b);
}

 med3目的是三数取中。

int med3(struct fre_word *f, int a, int b, int c)
{
	return f[a].num< f[b].num ? (f[b].num < f[c].num ? b : f[a].num < f[c].num ? c : a) : f[b].num > f[c].num ? b : f[a].num > f[c].num ? c : a;
}

  

结论:但是从测试结果来看,跟排序算法关系并不大,所耗时间几乎是没改变的,也就是说那么多高端的方法并没有什么实质性的提升,真正影响性能的还是在程序主体。但是在这次改进排序的过程中,改正了之前程序里的一些边界情况,也使得程序可以处理稍大些的文件了,收获还是挺大的。

 

https:https://git.coding.net/gongcr/word-frequency.git

ssh:[email protected]:gongcr/word-frequency.git

git:git://git.coding.net/gongcr/word-frequency.git  

时间: 2024-11-08 11:32:45

效能分析——词频统计1.1版的相关文章

效能分析——词频统计的java实现方法的第一次改进

java效能分析可以使用新版本jdk自带的jvisualvm工具进行统计 由于词频统计的运行在本人使用的机器上运行很快,无法被jvisualvm捕捉到线程的运行,所以捕捉的是eclipse的运行波动间接反映词频统计的效能 捕捉到的快照如下: 词频统计处理的文件为WarAndPeace,大小3282KB约3.3MB,输出结果到文件 在程序本身内开始和结束分别加入时间戳,差值平均为480-490ms.

分析“词频统计“项目进程

目录 功能需求 代码实现 psp 功能需求 1.小文件输入 2.支持命令行输入英文作品的文件名 3.支持命令行输入存储有英文作品文件的目录名,批量统计 4从控制台读入英文单篇作品 代码实现 本次代码实现了功能3. 类名 功能 void main(String[]) 主函数,调用其他函数实现基本功能 void SortMap(Map<String ,Integer>) 对Map进行排序 void Outputlist(Scanner) 对所给目录下文档进行统计并输出 void wordcont(

词频统计多需求版

下面针对词频统计的不同功能要求给出部分代码和截图,具体代码请访问博客下方提供的链接. 功能1. 小文件输入. 为表明程序能跑,结果真实而不是迫害老五,请他亲自键盘在控制台下输入命令. 部分代码: public static void main(String[] args) throws IOException { FileReader file; BufferedReader buffer; Map<String, Integer> hashMap = new HashMap<Strin

效能分析——词频统计器(第二版)

第一次分析结果: 分析: 整个词频统计器的代码都放在了main()一个函数里,导致无法分析程序效能 改进: 将代码分块书写 问题: 大的TXT文件在devc++编译器下可以运行,在VS下运行出错

词频统计(WEB版)

通过点击浏览按钮输入文件: 点击查询按钮后返回结果: 前台代码: 1 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> 2 3 <!DOCTYPE html> 4 5 <html xmlns="http://www.w3.org/1999/xhtm

词频统计单元测试--------第二版

在上一次的单元测试的基础上,我单独写了一个测试类对 单词树进行遍历的方法sortAndOutput() 进行测试,下图是这个方法的展示,他返回的是一个Map,Map里面存的是对应的单词以及其出现的次数. /* * 对文章用generateCharTree()函数生成单词树,在对生成的单词树进行排序并且输出 */ public Map sortAndOutput(String filePath) throws IOException { reader = new FileReader(filePa

词频统计1.1版——单元测试

前言:网上讲c语言单元测试的内容确实不太多,很多讲单元测试的都注重讲了单元测试的重要性.cppunit.junit的用法,但是没找到具体该如何进行单元测试的帖子,这就导致这几天知道了单元测试很重要,却不知道怎么写好这个测试,网上教程里的例子都是Assert.AreEqual,所以目前的收获很有限,试着在vs里写了几个测试,但是感觉并没有抓住单元测试的精髓,迷惑的很,希望老师多多指点.不过很神奇的一点是,我很深刻的认识到了单元测试的实用性,因为我以前写程序的时候,整体编译运行的时候如果出错了,自己

词频统计效能测试---------第二版

在第一次的词频统计中,对JProfile 款软件不是很熟悉,感觉数据不是很准确,在程序启动时JProfile总是提示Java虚拟机已退出,后来经过查阅知道解决方案:截图如下   要将 keep vm alive 勾选上. 程序总体总体情况如下: 当程序运行之后,cpu和内存的使用几乎在同一时间有一个明显的上升过程. 各个对象使用情况如下 下面是热点函数的展示,这也和我在程序中运用时间戳确定建树函数[generateCharTree()]占用时间较多的情况相符.因为对这个程序来说主要时间都花费在单

词频统计及效能分析

1. 博客开头给出自己的基本信息,格式建议如下:   学号:2017*****7254:   姓名:薛思语;   码云项目仓库:https://gitee.com/xsy990611/master/blob/master/word_freq.py 2. 程序分析,对程序中的四个函数做简要说明.要求附上每一段代码及对应的说明. 首先声明编码方式和导入string模块中的punctuation方法 # -*- coding: UTF-8 -*- from string import punctuat