HW—词频统计

第一次个人作业——词频统计

第一次做这种大作业,明显感觉陌生,各种规范和技能也是第一次使用,希望自己好运。

目录:一、基本要求

           二、需求分析及时间估计

           三、实现思路及过程

           四、测试用例、时间性能分析及改进方法

           五、经验总结

  

一、基本要求  

1. 统计文件的字符数(只需要统计Ascii码,汉字不用考虑,换行符不用考虑,'\0'不用考虑)(ascii码大小在[32,126]之间)

2. 统计文件的单词总数

3. 统计文件的总行数(任何字符构成的行,都需要统计)(不要只看换行符的数量,要小心最后一行没有换行符的情形)(空行算一行)

4. 统计文件中各单词的出现次数,输出频率最高的10个。

5. 对给定文件夹及其递归子文件夹下的所有文件进行统计

6. 统计两个单词(词组)在一起的频率,输出频率最高的前10个。

7. 在Linux系统下,进行性能分析,过程写到blog中(附加题) 

注意:

a) 空格,水平制表符,换行符,均算字符

b) 单词的定义:至少以4个英文字母开头,跟上字母数字符号,单词以分隔符分割,不区分大小写。

分割符:空格,非字母数字符号

例如:”file123”是一个单词,”123file”不是一个单词。file,File和FILE是同一个单词。

如果两个单词只有最后的数字结尾不同,则认为是同一个单词,例如,windows,windows95和windows7是同一个单词;

输出按字典顺序,例如,windows95,windows98和windows2000同时出现时,输出windows2000

c)词组的定义:windows95 good, windows2000 good123,可以算是同一种词组。按照词典顺序输出。

两个合法单词之间,出现一个非法字符串,比如:windows2000 abc good123,因为abc按照定义不是单词,因此这个词组其实是windows2000 good123,中间的abc当做分隔符看待。

两个单词分属两行,也可以直接组成一个词组。统计词组,只看顺序上,是否相邻。

d) 输入文件名以命令行参数传入。需要遍历整个文件夹时,则要输入文件夹的路径。

e) 输出文件result.txt

characters: number

words: number

lines: number

<word>: number

<word>为文件中真实出现的单词大小写格式,例如,如果文件中只出现了File和file,程序不应当输出FILE,且<word>按字典顺序(基于ASCII)排列,上例中程序应该输出File: 2

f) 根据命令行参数判断是否为目录

g) 将所有文件中的词汇,进行统计,最终只输出一个整体的词频统计结果。

 

二、需求分析及时间估计

1.统计字符总数及行数;

2.甄别单词并予以统计;

3.甄别词组并予以统计;

4.根据频率对单词、词组各自排序;

5.实现对文件夹及子文件夹的遍历;

PSP表格:

 

 

由表可看出,大部分阶段都是超时完成的,亟需改进;整体来看效率也比较低。

 

三、实现思路及过程

*结构体定义

 

1.统计字符总数及行数

这个就是遍历一下文件,遇到ascii值在32~126之间的就计数,行数统计则是统计换行符的个数,针对最后一个字符表示换行符的文件额外再加一即可。

 

2.甄别单词并予以统计

从文件第一个字符开始或者从某一分隔符开始,若检测到字母则开始借助flag标志辨别单词,当连续字母达到四个时说明找到单词,之后继续扫描并依次写入临时数组直到遇见分隔符;如果在连续遇到1~3个字母后被打断,则用标志mark判断若被数字打断则当前字符串作废,继续扫描直到遇见分隔符然后开始下一次单词甄别,如果是被分隔符打断则可以直接开始寻找下一个单词。注意最后退出的时候要判断一下当前字符串是否为单词。

统计部分则是在上述代码中增设一个临时数组b,实时存储字符串,当字符串无效时清空该数组,直到其为一个合法的单词,此时将其插入哈希表,通过单词首字母确定52个元素,按自然顺序1~52构造其哈希地址,用常数52定址解决冲突,若遇到等价的单词则判断字典顺序决定是否覆盖,若没有则新占一个槽。下面是哈希部分的代码:

 

 

3.甄别数组并予以统计

这部分我没什么好的思路,基本就是每次成功甄别到一个单词就用临时数组temp记录它,当下一个单词找到时,就把temp和b代入哈希函数去寻址(以temp首字母为自变量),哈希表构造与操作同上。套路与单词统计基本一致,代码不再展示。

 

4.根据频率对单词、词组各自排序

由于只需要输出频率最高的10个单词及10个词组,堆排序是最好的方式。

数组a按序包含了所有单词在word结构体数组(也就是哈希表)中的下标。算法是以单词频率为排序依据,对每个单词在word数组中的下标进行排序,当已经排好前十个时停止排序并打印结果。对词组的排序与之相同,不再赘述。

 

5.实现对文件夹及子文件夹的遍历

 查阅资料之后得知可以用句柄递归遍历文件夹,从而获取当前文件夹里所有文件的路径,然后处理一下将路径中的‘ \ ’换成 ‘ / ’即可被fopen调用来打开文件了。

getFiles函数用于获取当前文件夹下所有文件的路径。

 

完整的源代码地址:https://github.com/ustcychu/HW1_PB16060445.git

 

四、测试用例及时间性能分析

1.第一次调试用了个555k的文件夹,然后用了7.688秒orz,所以就靠优化工作了。

主函数中的热行当然在于调用分析函数statistics()。

 

 

statistics函数中的热行在于两次构造哈希表查找空槽和判断是否等价的过程,而且词组部分的耗时明显高于单词部分。

 

所以首先该分析的是JudgeWordEqual函数。其大致工作流程是判断俩字符串长度大小关系然后从后往前扫描,如果最后一段数字之前(如果有的话)的部分等价就判定俩单词等价,然再从头遍历判断二者字典顺序并予以覆盖,方便后续操作。

分析结果显示,大部分判断长度大小关系的结果都是二者相等,所以应放在第一个判断从句;用strlen取字符串长度耗时较多;上述两次遍历时间太长。

因此决定先针对性优化,效果不好就尝试别的方法。经过改进,时间缩至6.56秒。

接着我又重写了一种方法:

从两个字符串末尾开始扫描直到非数字的字符,将这之前的字符串片段取出进行不区分字母大小写的比较(stricmp),若匹配则说明俩字符串等价,然后用strcmp判断二者字典顺序选择是否进行覆盖,方便之后的操作。

 

似乎有了进步—5.01秒,但好像也不是特别好qaq。

再在lb--后面加上判断la与lb是否相等的判断以避免不必要的运算—时间缩至4.833秒。

之后再经过分析认为可能是哈希函数的问题,于是作了修改(主要就是扩大哈希函数的值域以减少搜索):

对应的查找与插入:

事实上,哈希函数如果给自变量加权的话可能效果更好,还有散列函数还可以选择二次探测法和拉链法(有时间的话再写一份拉链法的毕竟指针操作快很多 可惜开始没有想到),出于时间限制没有继续写下去了。

此次修改之后对应时间缩至1.633秒(还是有了一点点效果)。

 

2.测试空文件

(按要求空文件也记行 虽然不知道为啥要记...)

3.测试只有一个单词的文件

4.测试只有一行的文件:hhhh a1hhh hhhh lalalala

5.其他测试集 ( 优化前) 

A.(27k,0.018s)

B.(32k,0.024s)

 

C.(1M, 5.243秒)

 

6.其他测试集(优化后)

A.(1.2M, 2.56秒)

 

B.(5.2M,3.791秒)

 

C.(21M, 11.143秒)

附时间性能分析

可以看出代码的热行没有改变,改动的两个地方(JudgeWordEqual和哈希函数)的时间性能好了很多。

很明显可优化的地方还很多,今后继续学习逐渐进步。

 

 ***标准测试集(177M,21min)***

 

五、经验总结

通过本次实验,回顾了不少编程知识,也在看书浏览博客的过程中收获了很多技能;与之前的编程经历相比进步在于编程增加模块功能时结构更清晰、语句整理更熟练、细节bug明显减少,但在代码运行效率方面还有很大的进步空间,首先需要学习更多更高级的语言和工具,目前也是在进行中为团队项目做准备,其次是在编程算法上有待锻炼,目前感觉还是太老套,需要更多的阅读积累。希望通过本学期的学习能够很好地提升自己的软件编程能力,为今后做好准备。

 

转载于:https://www.cnblogs.com/notegeek/p/8654847.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/267350.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

oFono安装和启动

安装和启动oFono 1. git clone git://git.kernel.org/pub/scm/network/ofono/ofono.git 2. cd ofono 3. ./bootstrap-configure 或者./configure. configure过程中你可以需要装一些依赖包, 如&#xff1a; sudo apt-get install libudev-dev libdbus-1-dev libcap-ng-dev libto…

全排列问题(递归)

上次上课老师讲了全排列算法&#xff0c;现在刚刚看自己的写的全排列算法&#xff0c;看了好一会才看懂。。。。 应该是自己理解的不够彻底 所以今天彻彻底底的来分析一下 先看图&#xff1a; 思路&#xff1a; 先固定一个字符&#xff0c;然后将固定的字符与它后面的每一个进行…

php内核介绍及扩展开发指南,4.5. 发布扩展信息

发布扩展信息扩展可以发布 phpinfo() 或反射API要求的信息。我们一起来看一下。本章不会太长&#xff0c;因为真的很简单。MINFO( ) 挂钩如果声明了&#xff0c;一切都在声明的 MINFO() 挂钩中进行。如果未声明&#xff0c;则引擎将运行默认功能以打印有关扩展名的信息。该功能…

Ajax乱码解决方案

2019独角兽企业重金招聘Python工程师标准>>> 方案1: 页面端: <% page language"java" contentType"text/html; charsetgb2312" pageEncoding"gb2312"%> http://www.w3.org/TR/html4/loose.dtd"> Ajax: function ve…

花里胡哨,不协调统一的界面,正如看到一个穿花里胡哨衣服的人,让人作呕,不想接近。...

2019独角兽企业重金招聘Python工程师标准>>> 花里胡哨&#xff0c;不协调统一的界面&#xff0c;正如看到一个穿花里胡哨衣服的人&#xff0c;让人作呕&#xff0c;不想接近。 不要瞎变。 转载于:https://my.oschina.net/dongming/blog/40569

python全栈学习--day12(函数高级应用-带参数的装饰器,多个装饰器装饰一个函数)...

函数的执行时&#xff0c;*打散 函数的定义时&#xff0c;*聚合 from functools import wrapsdef wrapper(f):wraps(f)def inner(*args,**kwargs):执行函数之前的相关操作ret f(*args,**kwargs)执行函数之后的相关操作return retreturn inner wrapper def func1(*args):print…

选择排序法对数组进行排序

package selectionSort;import java.util.Arrays;public class Exam { //使用选择排序法对数组进行排序public static void main(String[] args) {int[] nums {23,3453,123,54,12,45,145,135,656,146,65};SelectionSort(nums);System.out.println(Arrays.toString(nums));}publ…

爬取校园新闻首页的新闻

1. 用requests库和BeautifulSoup库&#xff0c;爬取校园新闻首页新闻的标题、链接、正文。 import requests from bs4 import BeautifulSoup url requests.get("http://news.gzcc.cn/html/xiaoyuanxinwen/")url.encoding "utf-8" soup BeautifulSoup(…

php服务划分,云计算提供的服务分为哪三个层次

三个层次&#xff1a;1、基础设施即服务(IaaS)&#xff0c;向云计算提供商的个人或组织提供虚拟化计算资源&#xff1b;2、平台即服务(PaaS)&#xff0c;为开发人员提供通过全球互联网构建应用程序和服务的平台&#xff1b;3、软件即服务((SaaS)&#xff0c;通过互联网提供按需…

如何做个人职业规划和年度计划

在做规划的同时&#xff0c;已经结合工作和个人自身情况思考调整个人的职业规划以及2012年自己的学习成长计划。持续了大约2个月的时间&#xff0c;已经整理出了2012年自己的目标和计划。总结一下&#xff0c;制定个人规划大致分为几个步骤&#xff1a; 一、认识自己。主要包括…

centos 7 快速安装nginx

输入指令 vim /etc/yum.repos.d/nginx.repo 输入以下内容 [nginx] namenginx repo baseurlhttp://nginx.org/packages/centos/7/$basearch/ gpgcheck0 enabled1 wq 进行保存 验证是否安装成功 安装 yum install nginx 启动nginx服务 nginx 测试是否启动成功 在linux输入你的IP地…

matlab colorbar采用对数,matlab colorbar的使用 | 學步園

1&#xff1a;請問matlab中畫多張圖如何使用同一範圍的colorbar?例如生成了圖1,2,3生成圖1時&#xff0c;使用temp1caxis;將圖1的z值的取值範圍(即colorbar的取值範圍)取出。生成圖2,3時使用caxis(temp1)命令將圖2,3的z值的取值範圍設為同1相同。然後對各個同使用colorbar命令…

php拖拽原理,JS拖拽效果及原理解析

这篇文章主要介绍了如何实现js拖拽效果及原理解析,文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下元素拖拽分成3个步骤&#xff1a;按下鼠标&#xff0c;移动鼠标&#xff0c;松开鼠标。拖拽原理&#xff1a;按下…

jqGrid细节备注—pager文字的设置,更改默认的提交方式

默认的pager显示的文字&#xff0c;在英文版本下是如下 (file grid.locale-en.js): $.jgrid { defaults : { recordtext: "View {0} - {1} of {2}", emptyrecords: "No records to view", loadtext: "Loading...", pgtext : "Page {0} of …

浅谈拓扑排序

今天来讲讲拓扑排序 度娘告诉我 对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序&#xff0c;是将G中所有顶点排成一个线性序列&#xff0c;使得图中任意一对顶点u和v&#xff0c;若边(u,v)∈E(G)&#xff0c;则u在线性序列中出现在v之前。通常&#xff0c;这样…

makemid+matlab,《MATLAB基础》双语课

MATLAB双语教学视频第17讲MATLAB双语教学视频第18讲Summarizing DataIn this section...“Overview” on page 5-10“Measures of Location” on page 5-10“Measures of Scale” on page 5-11“Shape of a Distribution” on page 5-11OverviewMany MATLAB functions enable y…

php获取页面的可视内容高度,网页制作技巧:获取页面可视区域的高度_css

文章简介&#xff1a;获取页面可视区域高度&#xff0c;获取页面高度&#xff0c;获取滚动条滚动上去的页面高度.function getWH(){ var wh {}; "Height Width".replace(/[^/s]/g,function(a){ var b a.toLowerCase(); wh[b]window["inner".concat(a)] d…

安装与配置-以前的某个程序安装已在安装计算机上创建挂起的文件操作......

今日在Windows XP SP2的计算机上&#xff0c;安装SQL Server 2000 Standard Edition&#xff0c;安装不上&#xff0c;错误信息如下&#xff1a; 文字描述为&#xff1a; 以前的某个程序安装已在安装计算机上创建挂起的文件操作。运行安装程序之前必须重新启动计算机。 解决方法…

带预览图的js切换效果!

效果图&#xff1a; js代码&#xff1a; var isIE (document.all) ? true : false;var $ function (id) {return "string" typeof id ? document.getElementById(id) : id; };var Class {create: function() {return function() { this.initialize.apply(this,…

Python成长之路【第七篇】:Python基础之装饰器

一、什么是装饰器 装饰&#xff1a;装饰既修饰&#xff0c;意指为其他函数添加新功能 器&#xff1a;器既函数 装饰器定义&#xff1a;本质就是函数&#xff0c;功能是为其他函数添加新功能 二、装饰器需要遵循的原则 1、不能修改装饰器的源代码&#xff08;开放封闭原则&#…