用hash表统计文本文件中每个单词出现的频率
2010-09-30 22:42
1306 查看
闲来无事,敲两行代码解解愁。
今天介绍一种用自已建立的hash表(hash链表)来统计一个输入文本文件中每个单词出现的频率,hash表的构造详见《编程珠玑》第15章。
一、主体思路:
(1)建立一个hash表;
--(a) hash函数:除留取余法,H(key) = key % size;
--(b) 解决冲突的方法:链地址法,将所有映射到相同索引的字符串用链接指针连接在一起。
(2)读取文本文件word.txt,每次读取一行,然后分隔每个单词,插入到hash表,插入过程中会对单词出现次数统计;
(3)将整个hash表内容写到一个文本文件result.txt中。
二、数据结构及算法实现
(1)hash表
--(a) hash表大小(HASHNUMBER):采用一个大质数作为表的总容量,本例中为HASHNUMBER29989;
#define HASHNUMBER 29989 //散列表的大小,29989为质数。
#define MULT 31 //hash函数的一个乘子。
typedef struct hashnode
{//链表中每个节点的结构
hashnode()
{
word = NULL;
count = 0;
next = NULL;
}
char * word;//单词
int count;//出现频率
struct hashnode *next;//指向链表中具有相同hash值的下个节点
}hashNode,*hashNodePtr
;
hashNodePtr bin[HASHNUMBER] = { NULL};//HASHNUMBER大小的指针数组
作为hash表。
--(b) hash函数:将每个单词映射为一个小于HASHNUMBER的正整数;
unsigned int hashIndex(const char * pWord)//返回hash表索引(即hash指针数组的下标)。
{
assert(pWord != NULL);
unsigned int index = 0; //以下四行为将一个单词映射到一个小于HASHNUMBER的正整数的函数。
for(;*pWord != '/0';pWord++)
index = MULT * index + *pWord;
return index % HASHNUMBER;
}
--(c) 向hash表中插入单词。
void
insertWord
(const
char
* pWord
)//
在hash
表中插入单词,如果已经存在了,则增加单词的出现次数count
。
{
assert
(pWord
!= NULL
);
hashNodePtr
p
;
unsigned
int
index
= hashIndex
(pWord
);//用(b)中的hash函数得到单词在hash表中的下标。
for
(p
=bin
[index
];p
!= NULL
;p
= p
->next
)
{//
查找是否单词已经在hash
表中了。
if
(strcmp
(pWord
,p
->word
) ==
0)
{//
找到,将单词出现次数加.
(p
->count
)++;
return
;
}
}
p
= (hashNodePtr
)malloc
(sizeof
(hashNode
));//hash
表中不存在该单词,创建节点。
p
->count
= 1;//出现次数设置为1。
p
->word
= (char
*)malloc
(strlen
(pWord
)+1);
strcpy
(p
->word
,pWord
);
p
->next
= bin
[index
];//将新生成的节点插入到index为下标的链表中去。
bin
[index
] = p
;
}
(2)读取Data.txt中的单词,并将每个单词插入到(1)中设计好的hash表中。
void
readWordToHashTable
(const
char
*path
)
{//
从文本文件中读取单词,插入到hash
表中。
FILE
*fp
;
char
buf
[1024];//
存储一行字符串。
char
*p
;
fp
= fopen
(path
,"r"
);
if
(fp
== NULL
)
{
printf
("open file error!exit/n"
);
exit
(-1);
}
while
(NULL
!= fgets
(buf
,sizeof
(buf
),fp
))//数据读完,到文本末尾了
{
buf
[strlen
(buf
)-1]
= '/0'
; //
除去单词最后的换行符
//printf("%s/n",buf);
if
(strcmp
(""
,buf
)==0)//blank
line,continue.
continue
;
p
= strtok
(buf
,"'/t',' ','/n'"
);//用strtok函数从一行字符串中分离出每个单词,分隔符设置为(空格、逗号、换行、制表符)。
while
(p
!= NULL
)
{
insertWord
(p
);//
调用insertWord(),向hash
表中插入分隔出来的单词。
p
= strtok
(NULL
,"'/t',' ','/n'"
);
}
}
fclose
(fp
);
}
(3) 将hash表中对每个单词的统计信息写入到文本文件中。
void
writeHashTable
(const
char
*path
)
{//
将结果写到path
中。
FILE
*fp
;
hashNodePtr
p
;
int
i
;
fp
= fopen
(path
,"w"
);
if
(fp
== NULL
)
{
printf
("write file error! exit"
);
exit
(-1);
}
for
(i
=0;i
<HASHNUMBER
;i
++)
{
for
(p
= bin
[i
];p
!= NULL
;p
= p
->next
)
{
fprintf
(fp
,"Index %d:
<%s,%d>"
,i
,p
->word
,p
->count
);
if
(p
->next
== NULL
)
fprintf
(fp
,"/n"
);
}
}
fclose
(fp
);
}
(4)释放hash表中占用的内存
void freeHashTable()//释放hash表所占用内存。
{
int i;
hashNodePtr p,q;
p = q = NULL;
for(i=0;i<HASHNUMBER;i++)
{
p = bin[i];
while(p != NULL)
{
q = p;
p = p->next;
free(q->word);
free(q);
}
}
}
(5)
main函数中。
int
main
(void
)
{
readWordToHashTable
("data.txt"
);
writeHashTable
("result.txt"
);
return
0;
}
今天介绍一种用自已建立的hash表(hash链表)来统计一个输入文本文件中每个单词出现的频率,hash表的构造详见《编程珠玑》第15章。
一、主体思路:
(1)建立一个hash表;
--(a) hash函数:除留取余法,H(key) = key % size;
--(b) 解决冲突的方法:链地址法,将所有映射到相同索引的字符串用链接指针连接在一起。
(2)读取文本文件word.txt,每次读取一行,然后分隔每个单词,插入到hash表,插入过程中会对单词出现次数统计;
(3)将整个hash表内容写到一个文本文件result.txt中。
二、数据结构及算法实现
(1)hash表
--(a) hash表大小(HASHNUMBER):采用一个大质数作为表的总容量,本例中为HASHNUMBER29989;
#define HASHNUMBER 29989 //散列表的大小,29989为质数。
#define MULT 31 //hash函数的一个乘子。
typedef struct hashnode
{//链表中每个节点的结构
hashnode()
{
word = NULL;
count = 0;
next = NULL;
}
char * word;//单词
int count;//出现频率
struct hashnode *next;//指向链表中具有相同hash值的下个节点
}hashNode,*hashNodePtr
;
hashNodePtr bin[HASHNUMBER] = { NULL};//HASHNUMBER大小的指针数组
作为hash表。
--(b) hash函数:将每个单词映射为一个小于HASHNUMBER的正整数;
unsigned int hashIndex(const char * pWord)//返回hash表索引(即hash指针数组的下标)。
{
assert(pWord != NULL);
unsigned int index = 0; //以下四行为将一个单词映射到一个小于HASHNUMBER的正整数的函数。
for(;*pWord != '/0';pWord++)
index = MULT * index + *pWord;
return index % HASHNUMBER;
}
--(c) 向hash表中插入单词。
void
insertWord
(const
char
* pWord
)//
在hash
表中插入单词,如果已经存在了,则增加单词的出现次数count
。
{
assert
(pWord
!= NULL
);
hashNodePtr
p
;
unsigned
int
index
= hashIndex
(pWord
);//用(b)中的hash函数得到单词在hash表中的下标。
for
(p
=bin
[index
];p
!= NULL
;p
= p
->next
)
{//
查找是否单词已经在hash
表中了。
if
(strcmp
(pWord
,p
->word
) ==
0)
{//
找到,将单词出现次数加.
(p
->count
)++;
return
;
}
}
p
= (hashNodePtr
)malloc
(sizeof
(hashNode
));//hash
表中不存在该单词,创建节点。
p
->count
= 1;//出现次数设置为1。
p
->word
= (char
*)malloc
(strlen
(pWord
)+1);
strcpy
(p
->word
,pWord
);
p
->next
= bin
[index
];//将新生成的节点插入到index为下标的链表中去。
bin
[index
] = p
;
}
(2)读取Data.txt中的单词,并将每个单词插入到(1)中设计好的hash表中。
void
readWordToHashTable
(const
char
*path
)
{//
从文本文件中读取单词,插入到hash
表中。
FILE
*fp
;
char
buf
[1024];//
存储一行字符串。
char
*p
;
fp
= fopen
(path
,"r"
);
if
(fp
== NULL
)
{
printf
("open file error!exit/n"
);
exit
(-1);
}
while
(NULL
!= fgets
(buf
,sizeof
(buf
),fp
))//数据读完,到文本末尾了
{
buf
[strlen
(buf
)-1]
= '/0'
; //
除去单词最后的换行符
//printf("%s/n",buf);
if
(strcmp
(""
,buf
)==0)//blank
line,continue.
continue
;
p
= strtok
(buf
,"'/t',' ','/n'"
);//用strtok函数从一行字符串中分离出每个单词,分隔符设置为(空格、逗号、换行、制表符)。
while
(p
!= NULL
)
{
insertWord
(p
);//
调用insertWord(),向hash
表中插入分隔出来的单词。
p
= strtok
(NULL
,"'/t',' ','/n'"
);
}
}
fclose
(fp
);
}
(3) 将hash表中对每个单词的统计信息写入到文本文件中。
void
writeHashTable
(const
char
*path
)
{//
将结果写到path
中。
FILE
*fp
;
hashNodePtr
p
;
int
i
;
fp
= fopen
(path
,"w"
);
if
(fp
== NULL
)
{
printf
("write file error! exit"
);
exit
(-1);
}
for
(i
=0;i
<HASHNUMBER
;i
++)
{
for
(p
= bin
[i
];p
!= NULL
;p
= p
->next
)
{
fprintf
(fp
,"Index %d:
<%s,%d>"
,i
,p
->word
,p
->count
);
if
(p
->next
== NULL
)
fprintf
(fp
,"/n"
);
}
}
fclose
(fp
);
}
(4)释放hash表中占用的内存
void freeHashTable()//释放hash表所占用内存。
{
int i;
hashNodePtr p,q;
p = q = NULL;
for(i=0;i<HASHNUMBER;i++)
{
p = bin[i];
while(p != NULL)
{
q = p;
p = p->next;
free(q->word);
free(q);
}
}
}
(5)
main函数中。
int
main
(void
)
{
readWordToHashTable
("data.txt"
);
writeHashTable
("result.txt"
);
return
0;
}
相关文章推荐
- Linux下统计文本文件中前n个出现频率最高的单词
- 统计文件中各单词出现的频率(Hash表实现)
- go语言之map练习(二):编写一个程序wordfreq程序,统计输入文本中每个单词出现的频率(次数)
- Java编程:统计文本文件中单词出现频率
- 统计文本文件中单词出现频率(用java集合框架编写)
- 统计文本文件中单词出现频率(用java集合框架编写)
- 统计文本文件中单词出现频率,自己编写的Java小程序
- Hadoop:使用原生python编写MapReduce来统计文本文件中所有单词出现的频率功能
- 统计文本中每个单词出现的频率(附C++完整程序)
- 编写一个程序,统计给定文件中包含的每个单词出现的频率,并按单词表的顺序显示统计结果
- 统计一个大小为30kb~300kb的文本中各单词出现的频率,并输出前十个单词和进行程序性能分析
- 统计英文文件中单词数和各单词出现的频率(次数)
- python---字符串的拼接、去重、反转、字母花样排序、单词出现判断、统计文件特定单词频率lambda、硬盘容量、列表转字符串
- 模拟MapReduce编程的程序案例(用于统计文本中单词出现频率)
- 统计英文文本文档中前十个出现频率最多的单词
- 统计文本文件中单词出现次数最多的单词
- 统计文本中各单词出现的频率(JavaWeb)
- 统计输出某个文件中每个单词出现的次数
- Java实现读取键盘输入保存到txt文件,再统计并输出每个单词出现次数的方法