英文文本单词词频统计——基于HashTable

今天在面试的时候导师要求使用哈希表来统计一段文本中单词的词频,虽然比较简单但面试的时候居然没有完全写出来,哭死。

其实思路很简单,首先将文本中的单词提取出来存放到一个列表,这里没有使用jieba库,而是直接使用python提供split的方法,但是需要注意的是光分割字符串还不够,还要去除文本中的停用词,如括号、逗号、句号等。

在得到单词列表后,剩下的就是构建哈希表,然后统计词频了。哈希表的设计分为以下两步:

1.哈希函数

对于一个单词,如何计算它的哈希值?我们可以将单词各位的ascii码相加作为该单词的key,然后用除留余数法来计算哈希值,计算公式为hash(key) = key % p,p为一个较大的质数。

2.冲突处理
常用的冲突处理方法有开放定址法和拉链法,我采用的是拉链法,原理可以参考这幅图,如果计算得到的地址是空闲的,那么可以直接将结点放入该位置,并作为链表的头结点,否则检查链表中是否存在相同的单词如果存在则将对应单词的词频加一,如果不存在则将结点插入链表尾。
在这里插入图片描述
构建好哈希表后,我们只需要遍历哈希表中的所有结点,即可得到所有单词的词频,如下图所示:
在这里插入图片描述

代码实现如下:

text = """he National Wrestling Association was an early professional wrestling sanctioning body created in 1930 
by the National Boxing Association (NBA) (now the World Boxing Association, WBA) as an attempt to create a governing 
body for professional wrestling in the United States. The group created a number of "World" level 
championships as an attempt to clear up the professional wrestling rankings which at the time saw a number of
different championships promoted as the "true world championship". The National Wrestling Association's NWA 
World Heavyweight Championship was later considered part of the historical lineage of the National Wrestling 
Alliance's NWA World Heavyweight Championship when then National Wrestling Association champion Lou Thesz 
won the National Wrestling Alliance championship, folding the original championship into one title in 1949.
"""
HASH_NUM = 29989

class HashNode:
    """哈希表结点
    """
    def __init__(self, word, count):
        self.count = count
        self.word = word
        self.next = None

class HashTable:
    """哈希表
    """
    def __init__(self):
        self.table = [None] * HASH_NUM  # 哈希表 用列表的索引作为散列地址
        self.word_indexs = []  # 存放加入哈希表的单词的散列地址

    def hash(self, word):
        """哈希函数
            hash(key) = key % HASH_NUM
        """
        key = 0
        for ch in word:
            key = key + int(ord(ch))

        return key % HASH_NUM

    def add_word(self, word):
        """向哈希表中添加一个结点
        """
        index = self.hash(word)
        self.word_indexs.append(index)

        # 如果该位置不存在元素 则直接作为链表头结点
        if self.table[index] is None:
            self.table[index] = HashNode(word, 1)
            return

        # 寻找该位置对应的链表中是否有相同的单词
        node = self.table[index]
        while True:
            # 如果存在相同的单词 出现次数加一
            if node.word == word:
                node.count += 1
                return
            if node.next is None:
                break
            node = node.next

        # 否则新建一个结点插入链表尾
        new_node = HashNode(word, 1)
        node.next = new_node

    def display_count(self):
        """按降序顺序输出单词的词频
        """
        count_table = {}
       
        for index in list(set(self.word_indexs)):
            p = self.table[index]
            while p:
                count_table[p.word] = p.count
                p = p.next
            
        sorted_table = sorted(count_table.items(), key=lambda x: x[1], reverse=True)
        for key, value in sorted_table:
            print(key, ": ", value)


if __name__ == '__main__':
    split_words = text.split(' ')
    stop_words = ['\n', '"', ',', '.', '?', '"', '(', ')']
    word_list = []

    for word in split_words:
        # 去除停用词
        for stop_word in stop_words:
            word = word.strip(stop_word)
        word_list.append(word)

    hash_table = HashTable()
    for word in word_list:
        hash_table.add_word(word)
    hash_table.display_count()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用哈希表(Hash Table)来实现统计单词个数和出现频度。 具体步骤如下: 1. 读入文本文件,逐个字符读取并将其转换为小写字母,以便统计单词出现频度时不区分大小写。 2. 对于每个单词,先判断它是否已经在哈希存在,如果不存在,则将其加入哈希,并将它的出现次数设为1,如果已经存在,则将它的出现次数加1。 3. 统计完所有单词出现频度后,可以遍历哈希表,输出单词及其出现频度。 以下是一个示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define MAX_WORD_LENGTH 50 #define HASH_TABLE_SIZE 1000 // 定义哈希表节点结构体 typedef struct hash_node { char word[MAX_WORD_LENGTH]; int count; struct hash_node* next; } HashNode; // 定义哈希结构体 typedef struct hash_table { HashNode* nodes[HASH_TABLE_SIZE]; } HashTable; // 哈希函数 int hash(char* word) { int hash_value = 0; int i; for (i = 0; word[i] != '\0'; ++i) { hash_value = (hash_value * 31 + tolower(word[i])) % HASH_TABLE_SIZE; } return hash_value; } // 插入哈希表 void insert_hash_table(HashTable* table, char* word) { int index = hash(word); HashNode* node = table->nodes[index]; while (node != NULL) { if (strcmp(node->word, word) == 0) { node->count++; return; } node = node->next; } node = (HashNode*)malloc(sizeof(HashNode)); strcpy(node->word, word); node->count = 1; node->next = table->nodes[index]; table->nodes[index] = node; } // 打印哈希表 void print_hash_table(HashTable* table) { int i; for (i = 0; i < HASH_TABLE_SIZE; ++i) { HashNode* node = table->nodes[i]; while (node != NULL) { printf("%s: %d\n", node->word, node->count); node = node->next; } } } int main() { FILE* fp = fopen("input.txt", "r"); if (fp == NULL) { printf("Failed to open file.\n"); return 1; } HashTable table; memset(&table, 0, sizeof(table)); char word[MAX_WORD_LENGTH]; int i = 0, c; while ((c = fgetc(fp)) != EOF) { if (isalpha(c)) { word[i++] = tolower(c); } else if (i > 0) { word[i] = '\0'; insert_hash_table(&table, word); i = 0; } } if (i > 0) { word[i] = '\0'; insert_hash_table(&table, word); } fclose(fp); print_hash_table(&table); return 0; } ``` 在实际使用,可以根据需要对哈希表的大小进行调整,以便提高效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值