闲来无事,敲两行代码解解愁。
今天介绍一种用自已建立的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 )
{ //