2017-09-03 1 views
1

私はハッシュテーブルを実装していますが、いくつかの問題が発生しています。常に単語が追加されたときに更新されたハッシュテーブルを表示します。問題は、この単語が再び表示されるときに周波数を増やす必要があります。更新された頻度でもう一度印刷する:繰り返し単語を1回だけ印刷するにはどうすればよいですか?その頻度を示します。HashTable繰り返し単語を1回だけ印刷する方法は?

もう一つの問題は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; 
} 

出力:

https://imgur.com/a/PlRPp

+0

あなたが実際にハッシュテーブルをスキャンしません。 'chaves []'配列をスキャンします。この配列には、遭遇した順序で各単語のハッシュ値が含まれています。補助テーブルは必要ありません。 htable [hashval] - > palavra、htable [hashval] - 単純な 'for(hashval = 0; hashval freq); 'で十分です。 –

+2

残念ながら、基本的なバグもあります.2つの単語が同じ値にハッシュした場合、同じ単語として扱います。これは* [ハッシュコリジョン](https://en.wikipedia.org/wiki/Hash_table#Collision_resolution)*と呼ばれ、それを解決する方法はいくつかあります。私のお気に入りは、ノードを単一リンクリストにすることです。 (ところで、混合言語で書かれたコードを読むのは非常に難しいです。私は英語のネイティブスピーカーではありません.Cのキーワードは既に英語で書かれています。英語でのみ)。 –

+0

助けてくれてありがとうございました。私はこのコメントを申し訳なく思っています。そのすべてはポルトガルにあります。 '、btw、それは私の問題です。私はハッシュコリジョンをどう扱わないか、このための材料やコードはありますか? –

答えて

0

問題は、あなたがnode.palavraとして保存しているものです。トレースするとinserirHashTableの入力となり、strtokprocessarArquivoに呼び出した結果です。これは、ポインターが関数processarArquivo内のローカル変数lineである入力配列内にあるので、ものが毛むくじゃらしたものです。これは、ファイルから別の行をスキャンするか、この機能を終了すると無効になります。これは、ハッシュテーブル(processarArquivolineが有効な範囲にあります)を構築している間に正常に機能する理由です。関数が終了すると、未定義の動作になります(mainに戻り、print_freqに進んでください)。あなたがmallocを呼び出す方法

  • お知らせ:

    は今、inserirHashTableに改善するための2点があります。新しいHASH_TABLE構造体を保持するには、sizeof(char *)バイトを割り当てます。どうして?

  • さらに、ポインタをpalavraフィールドの値としてコピーしています。 make a copy hereする必要があります。

ボーナス問題はprint_freqでi変数、auxTableの存在とあなたはハッシュの値が間違っている一意であると仮定しているという事実未初期化されている(どのようにそれができる?以上1001の明確な言葉があります!)。

+0

ああ、私の問題はすべてprocessarArquivoにありますか?あなたはファイルを読んで、その単語をinserirHastTableに送ることができる方法を知っていますか? ' –

+0

@RafaelCamara私は文字列のコピーを作成する方法を提案します。あなたがファイルを読む方法は私にとってうまくいくようです。 – orhtej2

1

ここで私は衝突を解決する方法を説明し、必要に応じてすべての単語を再ハッシュすることなくハッシュテーブルのサイズを変更することもできます。

まず、単一のリンクリストを使用して、同じハッシュを持つすべての異なる単語を含めることにします。また、ハッシュテーブルのサイズを簡単に変更できるように、ハッシュ・フル・ハッシュ(モジュロ・ハッシュ・テーブル・サイズではありません)を保存します。最後に、私は、単語自体にC99 可撓性アレイ部材を使用したい:

struct hash_entry { 
    struct hash_entry *next; /* Pointer to next word in this hash table entry */ 
    size_t    hash; /* Any unsigned type works; I just like size_t */ 
    size_t    freq; /* Frequency */ 
    char    word[]; /* C99 flexible array member */ 
}; 

ハッシュテーブルは単独リンクリストにあるhashにハッシュ各単語と、sizeポインタのちょうど配列でありますentry[hash % size]をオフにぶら下がっ:

struct hash_table { 
    size_t    size; 
    struct hash_entry **entry; 
}; 

、初期化、サイズ変更、および無料のハッシュテーブルへの基本的な機能は、

int hash_table_create(struct hash_table *ht, size_t size) 
{ 
    size_t i; 

    if (ht == NULL || size < 1) 
     return -1; /* Invalid parameters */ 

    ht->size = size; 
    ht->entry = malloc(size * sizeof ht->entry[0]); 
    if (ht->entry == NULL) 
     return -2; /* Cannot allocate memory */ 

    /* Clear all entries: no hashes/chains yet! */ 
    for (i = 0; i < size; i++)   
     ht->entry[i] = NULL; 

    return 0; /* Success, no errors. */ 
} 

void hash_entry_free(struct hash_entry *entry) 
{ 
    while (entry) { 
     struct hash_entry *next = entry->next; 

     /* I like to "poison" the freed entries; 
      this makes debugging easier, if you try 
      to access an already freed entry. */ 
     entry->hash = 0; 
     entry->freq = 0; 
     entry->next = NULL; 

     free(entry); 

     entry = next; 
    } 
} 

void hash_table_free(struct hash_table *ht) 
{ 
    if (ht != NULL) { 
     size_t i; 

     for (i = 0; i < ht->size; i++) 
      if (ht->entry[i] != NULL) 
       hash_entry_free(ht->entry[i]); 

     free(ht->entry); 

     ht->size = 0; 
     ht->entry = NULL; 
    } 
} 

int hash_table_resize(struct hash_table *ht, size_t new_size) 
{ 
    struct hash_entry **entry; 
    struct hash_entry *curr, *next; 
    size_t i, k; 

    if (!ht || new_size < 1) 
     return -1; /* Invalid parameters */ 

    if (ht->size < 1 || !ht->entry) 
     return -2; /* Hash table is already freed */ 

    entry = malloc(new_size * sizeof entry[0]); 
    if (!entry) 
     return -3; /* Not enough memory */ 

    for (i = 0; i < new_size; i++) 
     entry[i] = NULL; 

    for (i = 0; i < ht->size; i++) { 

     /* Chain in the old hash table entry */ 
     curr = ht->entry[i];    

     /* We are paranoid, and clear the old entry. */ 
     ht->entry[i] = NULL; 

     while (curr) { 
      /* Remember next hash in this chain */ 
      next = curr->next; 

      /* Index to the new hash table */ 
      k = curr->hash % new_size; 

      /* Prepend in front of the new hash table entry chain */ 
      curr->next = entry[k]; 
      entry[k] = curr; 

      /* Advance to the next entry in the old chain */ 
      curr = next; 
     } 

    /* The old table is now useless. Free it, and use the new one. */ 
    free(ht->entry); 
    ht->entry = entry; 
    ht->size = new_size; 

    return 0; /* Success; no errors. */ 
} 
012です

機能をハッシュするように、私はdjb2 xor hashのように実行します。

size_t hash(const char *s) 
{ 
    if (s != NULL) { 
     size_t result = 5381; 

     while (*s != '\0') 
      result = (result * 33)^(*(s++)); 

     return result; 
    } else 
     return 0; 
} 

size_t hash_len(const char *s, const size_t len) 
{ 
    if (s != NULL) { 
     const char *z = s + len; 
     size_t result = 5381; 

     while (s < z) 
      result = (result * 33)^(*(s++)); 

     return result; 
    } else 
     return 0; 
} 

私は、2つの関数にハッシュテーブルに文字列/単語を追加することで分割したい:最初の関数は、それにstruct hash_entryコピー元の単語を作成します、第2の機能は、エントリを作成する最初のものを使用し、その後、ちょうどハッシュテーブルに追加:

struct hash_entry *hash_entry_new_len(const char *src, size_t len) 
{ 
    struct hash_entry *h; 

    if (len > 0 && !src) 
     return NULL; /* NULL src, but positive len! */ 

    /* To accommodate the flexible array member, we need 
     to add its size to the structure size. Since it 
     is a string, we need to include room for the '\0'. */ 
    h = malloc(sizeof (struct hash_entry) + len + 1); 
    if (!h) 
     return NULL; /* Out of memory */ 

    /* Copy the string to the entry, */ 
    if (len > 0) 
     memcpy(h->word, src, len); 

    /* Add the string-terminating nul char, */ 
    h->word[len] = '\0'; 

    /* clear the next pointer, */ 
    h->next = NULL; 

    /* set the frequency count to 1, */ 
    h->freq = 1; 

    /* and compute the hash. */ 
    h->hash = hash_len(src, len); 

    /* Done! */ 
    return h; 
} 

struct hash_entry *hash_entry_new(const char *src) 
{ 
    const size_t len = (src) ? strlen(src) : 0; 
    return hash_entry_new_len(src, len); 
} 

struct hash_entry *hash_table_add_part(struct hash_table *ht, const char *src, const size_t len) 
{ 
    struct hash_entry *h; 
    size_t    k; 

    if (!ht || ht->size < 1) 
     return NULL; /* No hash table! */ 

    /* We'll check src and len, so we report the right error. */ 
    if (!src && len > 0) 
     return NULL; /* Invalid src (NULL)! */ 

    h = hash_entry_new(src, len); 
    if (!h) 
     return NULL; /* Must be out of memory! */ 

    /* Index into the hash table */ 
    k = h->hash % ht->size; 

    /* Prepend new hash table entry to the beginning of the chain. */ 
    h->next = ht->entry[k]; 
    ht->entry[k] = h; 

    /* Success! */ 
    return h; 
} 

/* Helper function, so you don't need to specify the length 
    if you wish to add a copy of entire source string. */ 
struct hash_entry *hash_table_add(struct hash_table *ht, const char *src) 
{ 
    const size_t len = (src) ? strlen(src) : 0; 
    return hash_table_add_part(ht, src, len); 
} 

len = (src) ? strlen(src) : 0発現はif (src != NULL) len = strlen(src); else len = 0;の省略形です。私は、文字列の長さをチェックする安全な方法として、または文字列が空またはNULLの場合は0を使用して、多くを使用します。

NULL文字列はハッシュ0を受け取りますが、空の文字列は5381にハッシュされます。それは重要ではありません、私はちょうどそのように(またはまったく、過度にニッキーピックで熱気に満ちた、彼らが言うように)点をつけるのが好きです。私の「ノーマル」の機能は同じ名前を持つが、_len()サフィックスのない機能で、_len()で終わる

注文字列全体を使用するヘルパー関数です。文字列を分割するのにstrtok()を使用しない場合は便利です。 strspn()/strcspn()、または正規表現でさえ、各文字列内の興味深い単語を見つけることができます。

ハッシュテーブル内の特定の単語を見つけるには、元の文字列を比較する必要があります。ハッシュ自体は十分ではありません。単語の頻度を数える

struct hash_entry *hash_table_find_len(struct hash_table *ht, const char *src, const size_t len) 
{ 
    const size_t hashval = hash_len(src, len); 
    struct hash_entry *curr = ht->entry[hashval % ht->size]; 

    /* No matches for sure? */ 
    if (!curr) 
     return NULL; 

    /* We have a chain (singly-linked list). 
     Check each one in turn. */ 
    while (curr) { 

     /* Since we kept the entire hash value, 
      and not just the index to the hash table, 
      we can use the extra bits to exclude 
      words that have the same hash modulus (index) 
      but different complete hash value! */ 
     if (curr->hash == hash) { 

      /* We cannot use strncmp() if len == 0, 
       so we check that case separately. */ 
      if (len == 0) { 
       if (curr->word[0] == '\0') 
        return curr; /* Match found! */ 
      } else { 
       if (!strncmp(curr->word, src, len) && 
        curr->word[len] == '\0') 
        return curr; /* Match found! */ 
      } 
     } 

     /* No match. Check next one in chain. */ 
     curr = curr->next; 
    } 

    /* Nope, no match. */ 
    return NULL; 
} 

struct hash_entry *hash_table_find(struct hash_table *ht, const char *src) 
{ 
    const size_t len = (src) ? strlen(src) : 0; 
    return hash_table_find_len(ht, src, len); 
} 

が今簡単です:

int hash_table_seen_len(struct hash_table *ht, const char *src, const size_t len) 
{ 
    struct hash_entry *h; 

    /* Sanity checks first. */ 
    if (!ht || (!src && len > 0)) 
     return -1; /* Invalid parameters! */ 

    h = hash_table_find_len(ht, src, len); 
    if (h) { 
     /* Found match; increment freq counter. */ 
     h->freq++; 
     /* All done. */ 
     return 0; 
    } 

    /* Not found. Add to hash table. */ 
    h = hash_table_add_len(ht, src, len); 
    if (!h) { 
     /* An error occurred; should be "out of memory", 
      since we checked the other causes earlier 
      in this function. */ 
     return -1; 
    } 

    /* The word was added to the hash table. 
     Since its freq count is 1, we do not need 
     to increment it; we're done. */ 
    return 0; 
} 

int hash_table_seen(struct hash_table *ht, const char *src) 
{ 
    const size_t len = (src) ? strlen(src) : 0; 
    return hash_table_seen_len(ht, src, len); 
} 

私は私がしたい、頻度順にハッシュテーブルエントリを印刷することをかなり確信しています最後に、私たちがのインタフェースを「盗む」ことができます

size_t hash_table_max_freq(struct hash_table *ht) 
{ 
    size_t result = 0; 
    size_t i; 

    if (!ht || ht->size < 1) 
     return 0; /* No hash table. */ 

    for (i = 0; i < ht->size; i++) { 
     struct hash_entry *curr = ht->entry[i]; 

     while (curr) { 
      if (curr->freq > result) 
       result = curr->freq; 
      curr = curr->next; 
     } 
    } 

    return result; 
} 

size_t hash_table_next_freq(struct hash_table *ht, const size_t max_freq) 
{ 
    size_t result = 0; 
    size_t i; 

    if (!ht || ht->size < 1) 
     return 0; /* No hash table. */ 

    for (i = 0; i < ht->size; i++) { 
     struct hash_entry *curr = ht->entry[i]; 

     while (curr) { 
      if (curr->freq > result && curr->freq < max_freq) 
       result = curr->freq; 
      curr = curr->next; 
     } 
    } 

    return result; 
} 

:所定の周波数よりも低い最大周波数を見つけるために、1の最大周波数を見つけるために、そして他の2つのヘルパー関数を使用します

int hash_table_for_all(struct hash_table *ht, 
         int (*func)(struct hash_entry *, void *), 
         void *user_data) 
{ 
    int  retval; 
    size_t i; 

    if (!ht || !func) 
     return -1; /* NULL hash table or function. */ 

    for (i = 0; i < ht->size; i++) { 
     struct hash_entry *curr = ht->entry[i]; 
     while (curr) { 
      retval = func(curr, user_data); 
      if (retval) 
       return retval; 
      curr = curr->next; 
     } 
    } 

    return 0; 
} 

int hash_table_for_freq(struct hash_table *ht, const size_t freq, 
         int (*func)(struct hash_entry *, void *), 
         void *user_data) 
{ 
    int  retval; 
    size_t i; 

    if (!ht || !func) 
     return -1; /* NULL hash table or function. */ 

    for (i = 0; i < ht->size; i++) { 
     struct hash_entry *curr = ht->entry[i]; 
     while (curr) { 
      if (curr->freq == freq) { 
       retval = func(curr, user_data); 
       if (retval) 
        return retval; 
      } 
      curr = curr->next; 
     } 
    } 

    return 0; 
} 

上記のコードのいずれでもコンパイルテストし、あなたがどんなタイプミスを見つける(またはコンパイル時のエラーに遭遇する)ので、もしではない、聞かせてください:すべての単語、または特定の周波数を持つすべての単語を見つけるため私はコメントで知っているので、私は確認して修正することができます。

0

私はあなたの運動を行いました。

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

//hash table size 
#define SIZE 1000 
//maximum size of the input string 
#define STR_LEN 100 

typedef struct linked_list { 
    unsigned char value[STR_LEN]; 
    unsigned int cnt; 
    struct linked_list *next; 
} linked_list; 

void print_items(int freq); 
void print_freq(int freq); 
void print_table(); 
int add_to_table(unsigned char *str); 
unsigned long get_hash(unsigned char *str); 

linked_list* table[SIZE]; 

int main() { 
    unsigned char str[STR_LEN]; 
    //the fgets function allows the spaces in the string. 
    //so, strings like: 'red green blue' are possible. 
    while(fgets(str, STR_LEN, stdin)) { 
     sscanf(str, "%[^\n]", str); 

     add_to_table(str); 
    } 

    print_freq(2); 

    return 0; 
} 

void print_table(){ 
    puts("Whole table"); 
    print_items(0); 
} 

void print_freq(int freq){ 
    printf("Words with frequency: %d\n", freq); 
    print_items(freq); 
} 

// if freq = 0, it prints all hash table items. 
// if freq = 1, 2, 3... it prints only items with the specific frequency. 
void print_items(int freq) { 
    int i; 
    linked_list *node; 
    puts("----------------------"); 
    puts("Values\t| Frequency"); 
    for(i = 0; i < SIZE; i++) { 
     node = table[i]; 
     while(node) { 
      if(freq && freq != node->cnt) { 
       node = node->next; 
       continue; 
      } 
      printf("%s\t| %d\n", node->value, node->cnt); 
      node = node->next; 
     } 
    } 
    puts("----------------------"); 
} 

//Collision processing implemented by the linked list. 
//In the beginning, all items of the hash table are NULL. 
// 
//The first string with specific hash goes to the corresponding 'table' array index 
//in the linked list's node form. 
// 
//Then, if the collision occurs (different string with the same hash) 
//the new node shifts the previous node and linking to it 
int add_to_table(unsigned char *str) { 
     unsigned long hash; 
     hash = get_hash(str); 
     hash = hash & SIZE; 

     linked_list *node = table[hash]; 

     while(node) { 
      if(strcmp(str, node->value) == 0) { 
       node->cnt++;  
       return 1; 
      } 
      node = node->next; 
     } 

     //if the item does not exist (wasn't found in the previous while loop), 
     //the new node is created 
     linked_list *new_node = malloc(sizeof(linked_list)); 
     //the new node 'next' field is pointing to the previous 
     //first node (head) of the linked list 
     new_node->next = table[hash]; 
     new_node->cnt = 1; 
     strcpy(new_node->value, str); 

     //and the new node became the new 'head' 
     table[hash] = new_node; 

     print_table(); 

     return 1; 
} 

// the 'djb2' hash algorithm is used 
unsigned long get_hash(unsigned char *str) 
{ 
    unsigned long hash = 5381; 
    int c; 

    while (c = *str) { 
     hash = hash * 33 + c; 
     str++; 
    } 

    return hash; 
} 

テスト:

one       <--- input "one" 
Whole table     <--- output 
----------------------   the whole table is printed each time, 
Values | Frequency    the new string is added 
one  | 1 
---------------------- 
two       <--- input "two" 
Whole table 
---------------------- 
Values | Frequency 
two  | 1 
one  | 1 
---------------------- 
one       <--- input - no output, because the hash table 
            already have this string 
two       <--- input - the same 
three      <--- input - the output is appearing now, 
            'three' didn't inputted before 
Whole table 
---------------------- 
Values | Frequency 
two  | 2 
three | 1 
one  | 2 
---------------------- 
Words with frequency: 2  <--- I am send EOF (end of file) to the 
            program by Ctrl-D 
---------------------- 
Values | Frequency   
two  | 2 
one  | 2 
---------------------- 
関連する問題