c语言中如何用散列表的方法统计大文本词频,并按词频从大到小排序
时间: 2023-12-14 16:36:24 浏览: 36
在C语言中,可以使用散列表(也称哈希表)来统计大文本的词频,并按照词频从大到小排序。一般来说,散列表包括一个数组和一个哈希函数。哈希函数将每个词映射到散列表的一个位置上,然后在该位置上存储该词的出现次数。
以下是一个示例代码,它使用散列表和一个简单的排序算法来实现词频统计和排序:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_WORDS 10000
#define MAX_WORD_LEN 50
// 定义散列表节点
typedef struct {
char* word;
int count;
} HashNode;
// 计算哈希值
int hash(char* word) {
int hashval = 0;
while (*word != '\0') {
hashval = (hashval << 5) + *word++;
}
return hashval % MAX_WORDS;
}
// 创建散列表
HashNode** createHashTable() {
HashNode** table = malloc(sizeof(HashNode*) * MAX_WORDS);
for (int i = 0; i < MAX_WORDS; i++) {
table[i] = NULL;
}
return table;
}
// 插入单词到散列表中
void insertWord(HashNode** table, char* word) {
int hashval = hash(word);
HashNode* node = table[hashval];
while (node != NULL) {
if (strcmp(node->word, word) == 0) {
node->count++;
return;
}
node = node->next;
}
HashNode* new_node = malloc(sizeof(HashNode));
new_node->word = strdup(word);
new_node->count = 1;
new_node->next = table[hashval];
table[hashval] = new_node;
}
// 从散列表中删除单词
void deleteWord(HashNode** table, char* word) {
int hashval = hash(word);
HashNode* node = table[hashval];
HashNode* prev = NULL;
while (node != NULL) {
if (strcmp(node->word, word) == 0) {
if (prev == NULL) {
table[hashval] = node->next;
} else {
prev->next = node->next;
}
free(node->word);
free(node);
return;
}
prev = node;
node = node->next;
}
}
// 释放散列表
void freeHashTable(HashNode** table) {
for (int i = 0; i < MAX_WORDS; i++) {
HashNode* node = table[i];
while (node != NULL) {
HashNode* next = node->next;
free(node->word);
free(node);
node = next;
}
}
free(table);
}
// 比较函数,用于排序
int compare(const void* a, const void* b) {
const HashNode* node1 = *((const HashNode**)a);
const HashNode* node2 = *((const HashNode**)b);
return node2->count - node1->count;
}
// 根据词频从大到小排序
void sortHashTable(HashNode** table, HashNode** nodes) {
int count = 0;
for (int i = 0; i < MAX_WORDS; i++) {
HashNode* node = table[i];
while (node != NULL) {
nodes[count++] = node;
node = node->next;
}
}
qsort(nodes, count, sizeof(HashNode*), compare);
}
int main() {
// 读取大文本
char word[MAX_WORD_LEN];
HashNode** table = createHashTable();
while (scanf("%s", word) == 1) {
insertWord(table, word);
}
// 排序并输出结果
HashNode* nodes[MAX_WORDS];
sortHashTable(table, nodes);
for (int i = 0; i < MAX_WORDS && nodes[i] != NULL; i++) {
printf("%s: %d\n", nodes[i]->word, nodes[i]->count);
}
// 释放内存
freeHashTable(table);
return 0;
}
```
在这个示例代码中,我们首先定义了一个 `HashNode` 结构体来表示散列表的节点,其中包括单词和出现次数两个成员变量。然后我们定义了哈希函数 `hash`,它将每个单词映射到散列表中的一个位置上。接着我们实现了 `createHashTable`、`insertWord`、`deleteWord` 和 `freeHashTable` 函数,用于创建散列表、插入单词、删除单词和释放内存。最后我们实现了 `sortHashTable` 函数,它使用简单的排序算法将散列表中的节点按照词频从大到小排序。
在主函数中,我们通过读取大文本来统计词频,并使用 `sortHashTable` 函数将结果按照词频从大到小排序并输出。
需要注意的是,该示例代码中的散列表是一个开放定址散列表,它使用线性探测来解决哈希冲突。实际上,还有其他类型的散列表,例如链表散列表和二次探测散列表等,可以根据实际需求选择不同的散列表类型。