我正在實現一個hashTable,但我遇到了一些問題,我總是在添加一個單詞時打印更新後的hashtable,問題是,當這個單詞再次出現時,我只需要增加它的頻率,但我的程序是以更新的頻率再次打印:如何才能打印重複的文字一次?並顯示他們的頻率。HashTable如何僅打印一次重複的單詞?
我得到的另一個問題是函數print_freq。它接收到一個int freq,我應該打印這個頻率的單詞,但問題是,auxTable沒有從htable保存單詞,我不知道爲什麼它不工作,因爲auxtable保存頻率正常,但是當它要保存文字,它會保存一個空字符「」。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define HTABLE_SIZE 1001
#define MAX_LINE_SIZ 1024
/* Hash Table */
typedef struct node* HASH_TABLE; /* estrutura de dados utilizadas para formar a hastable*/
struct node {
char *palavra; /*word*/
int freq;
};
/*Declaracao das funcoes*/
void inserirHashTable(char *s);
void print_ht();
void print_test();
HASH_TABLE htable[HTABLE_SIZE] = { NULL }; /* Hash table que armazenará as palavras lidas do arquivos */
unsigned int chaves[HTABLE_SIZE]; /* Vetor que armazenará as chaves das palavras da tabela*/
int tamanhoChaves=-1; /*Variavel responsavel por contar a quantidade de chaves do vetor de chaves*/
int size = 0; /* variavel responsavel por armazenar o numero de elementos da tabela*/
/*Função responsavel por processar o arquivo, a mesma recebe o arquivo como parametro,
* pega cada palavra presente no arquivo separa dos simbolos ?!+.-... e chama a função
* inserirHT para inserir a palavra separada na tabela hash*/
void processarArquivo(FILE *fp)
{
const char *seperators = " ?!'\";,.:+-*&%(){}[]<>\\\t\n"; // caractertes que deveram ser separados
char line[MAX_LINE_SIZ];
char *s;
while((fgets(line,MAX_LINE_SIZ, fp)) != NULL) //pegando a linha do arquivo
{
for (s=strtok(line,seperators); s; s=strtok(NULL,seperators)){ // separando a palavra
/*printf("Palavra a ser inserida %s \n",s); printf utilizado para mostrar
* a palavra que foi seperada e será inserida*/
inserirHashTable(s);//Chamando a função inserir
}
}
}
/* Função responsavel por criar a chave de cada palavra que vai para tabela,
recebe como parametro um ponteiro para string, logo em seguida pega cada
caractere da string e gera um unsigned int para ele, retorna por fim o
modulo desse unsigned int pelo tamanho da tabela*/
unsigned int hash(char *tok)
{
unsigned int hv = 0;
while (*tok)
hv = (hv << 4) | toupper(*tok++);
/*printf("conversao: %d \n",hv); Printf utilizado para mostrar o valor de hv antes de ser retorna como modulo*/
return hv % HTABLE_SIZE;
}
/* funcao responsavel por isenrir a palavra lida do arquivo na hash_table,
* a funçãp recebe como parametro um ponteiro para estra palavra*/
void inserirHashTable(char *palavra) {
/*printf("Inserindo a palavra %s \n",palavra); Printf utilzado para mostrar a palavra a ser inserida na tabela*/
tamanhoChaves++; /*Assim que uma palavra é inserida o numero de chaves é incrementado*/
chaves[tamanhoChaves] = hash(palavra);/*A palavra é convertida na função hash e sua armazenada no vetor de chaves*/
unsigned int hashval = chaves[tamanhoChaves]; /*Chave da apalvra*/
if (htable[hashval]==NULL){
/*printf("indice %u de %s \n",hashval,palavra);Printf utilizado para mostrar a chave e a palavra a ser inserida*/
htable[hashval] = malloc(sizeof(palavra)); /*Alocando memoria para palavrra*/
htable[hashval]->palavra = palavra ; /*Inserindo a palavra*/
htable[hashval]->freq = 1; /*Incrementado sua frequencia*/
size++;
}else {
/*If a words already exists in the table, i just incremente her frequency and the size. I guess the problem for repeated word is in here*/
htable[hashval]->freq++;
size++;
}
/*A tabela é impressa a cada instante que uma palavra é inserida*/
printf("\nAtualização da tabela\n");
print_ht();/*Impressao das palavras já recebidas, a cada instante, com a quantidade de ocorrências*/
}
/* Function responsible to print the words that were addedd to the hash table*/
void print_ht() {
int i=0;
/*Tabela auxiliar que servira para impressao das palavras e suas chaves*/
HASH_TABLE *auxTable = (HASH_TABLE*) malloc(sizeof(HASH_TABLE)*size);
unsigned int hashval; /* variavel utilizada para pegar a chave das palavras no vetor de chaves */
for(i; i < size; i++){
hashval = chaves[i]; /*Pegando a chave*/
/*printf("indice %u de %s \n",hashval,htable[hashval]->token);Printf utilizado para ver a chave e a palavra*/
auxTable[i] = htable[hashval]; /*Atribuindo a palavra e a freq para tabela auxiliar*/
}
/*qsort(auxTable,size,sizeof(link),compare);*/
/*Imprimindo a tabela*/
printf("Palavra | Frequencia\n");
for (i=0; i < size; i++)
printf("%s \t %d\n",auxTable[i]->palavra,auxTable[i]->freq);
free(auxTable);
}
/*Funcion responsible to print the words with the frequency received in the paramater*/
void print_freq(int freq){
printf("Palavras com a frequencia: %d\n", freq);
int i, j =0;
HASH_TABLE *auxTable = (HASH_TABLE*) malloc(sizeof(HASH_TABLE)*size);
unsigned int hashval;
for(i; i < size; i++){
hashval = chaves[i];
/*printf("indice %u de %s \n",hashval,htable[hashval]->palavra);*/
auxTable[i] = htable[hashval]; /*Problem is in here, when I do this, the auxTable[i]->palavra(word) = "", but the freq has been saved normally n*/
}
printf("Palavra | Frequencia\n");
for (i=0; i < size; i++) {
if(auxTable[i]->freq == freq) {
printf("%s \t %d\n",auxTable[i]->palavra,auxTable[i]->freq); /*When I print, only the frequency is showed*/
}
}
free(auxTable);
}
int main(int argc, char *argv[])
{
int i;
FILE *fp;
fp = fopen("input.txt","r");
if (NULL == fp)
{
fprintf(stderr,"Error ao abrir o arquivo: %s\n",fp);
}
printf("Imprimindo processo \n");
processarArquivo(fp); /* debuuga aqui pra tu entender o q rola*/
fclose(fp);
print_freq(3); //should print the word with freq equal to 3
//print_ht();
/*clear_ht();*/
return 0;
}
輸出:
其實你不通過哈希表掃描;你掃描'chaves []'數組,它包含你遇到的每個單詞的哈希值。你也不需要輔助表;一個簡單的'for(hashval = 0; hashval palavra,htable [ - > freq);'應該就夠了。 –
不幸的是,你也有一個基本的錯誤:如果兩個單詞哈希到相同的值,你把它們當作同一個單詞。這被稱爲* [散列衝突](https://en.wikipedia.org/wiki/Hash_table#Collision_resolution)*,並且有幾種不同的方法可以解決它。我最喜歡的是把節點變成單鏈表。 (順便說一下,閱讀以混合語言編寫的代碼是非常困難的,我自己也不是英語母語的人,C關鍵字已經是英文的,所以當所有的代碼和評論都是) –
感謝幫助的人,我很抱歉這個評論,所有這些都是在葡萄牙 - ',順便說一句,這是我的問題,我不怎麼對待哈希校對,你有任何材料或代碼嗎? –