我正在尝试搜索哈希表,我遇到了一些问题。我的代码编译,但它有问题。我不太清楚是什么。当我在命令提示符下运行它,并将文件传递给程序。我在搜索方面遇到了一些问题
0虚伪
struct htablerec {
char **key;
int *frequencies;
int num_keys;
int capacity;
};
static unsigned int htable_word_to_int(char *word) {
unsigned int result = 0;
while (*word != '\0') {
result = (*word++ + 31 * result);
}
return result;
}
int htable_insert(htable h, char *str) {
int i;
/*convert string to integer*/
unsigned int index = htable_word_to_int(str);
/*calculate index to insert into hash table*/
int remainder = index%h->capacity;
/*once calculated position in the hash table, 3 possibilities occur*/
/*no string in this positon, copy string to that position,
increment number of keys, return 1*/
if (h->key[remainder] == NULL) {
char *key = emalloc(strlen(str) + 1);
strcpy(key, str);
h->key[remainder] = key;
h->frequencies[remainder] = 1;
h->num_keys++;
return 1;
}
/*the exact same string is at the position,
increment frequency at that position,
return frequency*/
if (strcmp(str, h->key[remainder]) == 0) {
h->frequencies[remainder]++;
return h->frequencies[remainder];
}/*a string is at that position, but it isnt the rightone,
keep moving along the array until you find either an open
space or the string you are looking for*/
if (h->key[remainder] != NULL && strcmp(str, h->key[remainder]) != 0) {
/*you may need to wrap back around to the beginning of the table,
so each time you add,to the position you should also mod
by the table capacity.*/
for (i = 0; i < h->capacity; i++) {
/*no string in this positon, copy string to that position,
increment number of keys*/
if (h->key[remainder] == NULL) {
char *key = emalloc(strlen(str) + 1);
strcpy(key, str);
h->key[remainder] = key;
h->frequencies[remainder] = 1;
h->num_keys++;
}
/*if you find the string you were looking for,
increment the frequency at the position
and return the frequency*/
if (strcmp(str, h->key[remainder]) == 0) {
h->frequencies[remainder]++;
return h->frequencies[remainder];
}
if (h->key[remainder] != NULL && h->capacity == i) {
i = 0;
}
}
}
/*if you have kept looking for an open space but there isnt one,
the hash table must fu*/
return 0;
}
int htable_search(htable h, char *str) {
/*create an initialise, a value to hold the number of collisions we have when looking for our key*/
int collisions = 0;
unsigned int index = htable_word_to_int(str);
/*calculate the position at which we should start looking for our key*/
int remainder = index%h->capacity;
/*while there is an item at that position, but it isn't the key, and we haven't yet checked the entire hash table*/
while (h->key[remainder] != NULL && strcmp(str, h->key[remainder]) != 0 && h->key[remainder] != h->key[h->capacity]) {
/*increment our position to look for the next cell*/
h->key[remainder]++;
/*increment the number of collisions we've had so far*/
collisions++;
}
/*if our number of collisions == the hashtable capacity*/
if(collisions == h->capacity) {
/*then out hashtable was full, did not contain our key, so we should return 0*/
return 0;
}
else {
/*else return the frequency at our final position*/
return h->frequencies[h->capacity];
}
}
#include <stdio.h>
#include <stdlib.h>
#include "mylib.h"
#include "htable.h"
int main(void) {
htable h = htable_new(113);
char word[256];
char op;
/*We must have a space before the %c*/
while(2 == scanf(" %c %255s", &op, word)) {
if ('+' == op) {
htable_insert(h, word);
}
else if ('?' == op) {
printf("%d %s\n", htable_search(h, word), word);
}
}
htable_free(h);
return EXIT_SUCCESS;
}
我已经在上面添加了mylib.c。
+ sociable
+ galleries
+ Russia
+ screamer
+ thickness
+ combed
+ escorted
+ revocable
+ digressed
+ Malawi
+ infringing
+ onslaught
+ files
+ kidded
+ unsound
+ tied
+ Ottawa
+ puzzles
+ build
+ necrosis
+ admire
+ cupful
+ brokers
+ segregation
+ Capet
+ Georges
+ bran
+ binders
+ zebras
+ contented
+ keypad
+ snowily
+ replaced
+ dominating
+ outright
+ Latinizers
+ invalidity
+ wakes
+ diversification
+ Riemannian
+ leadings
+ rhythmically
+ gentler
+ swarthy
+ disconnects
+ factoring
+ sequences
+ tiring
+ attendances
+ unloaded
? insincere
? constants
? unordered
? Toland
? butterfly
? suburban
? overtone
? Hauser
? numbers
? disadvantageous
? saintly
? Dutton
? homomorphic
? corporation
? climaxes
? dietitian
? manifestly
? greyest
? challenge
? tentacle
? Bernice
? bottle
? involve
? resisted
? wholesale
? trustworthiness
? Poole
? fourfold
? relentlessly
? fittingly
? doctorates
? cowlick
? Missoula
? curtsy
? calmness
? reallocate
? bossed
? scarce
? catheters
? regained
? autographing
? unobservable
? apprise
? lancer
? chicken
? crunches
? scrambled
? reared
? pealing
? violate
? sociable
? galleries
? Russia
? screamer
? thickness
? combed
? escorted
? revocable
? digressed
? Malawi
? infringing
? onslaught
? files
? kidded
? unsound
? tied
? Ottawa
? puzzles
? build
? necrosis
? admire
? cupful
? brokers
? segregation
? Capet
? Georges
? bran
? binders
? zebras
? contented
? keypad
? snowily
? replaced
? dominating
? outright
? Latinizers
? invalidity
? wakes
? diversification
? Riemannian
? leadings
? rhythmically
? gentler
? swarthy
? disconnects
? factoring
? sequences
? tiring
? attendances
? unloaded
这是我传入的文件的内容。我的插入方法有效,但如果需要,我也可以包含它。
答案 0 :(得分:0)
您的一些问题出现在for
内的htable_insert()
循环中:
return 1;
。您的环绕代码正在修改错误的变量(i
)。我认为应该是:
if (remainder >= h->capacity - 1)
remainder = 0;
else
remainder++;
您在搜索代码中也存在大致相同的问题。
建议:
如果您有一个相对复杂的数据结构,例如哈希表,则值得创建(和调试)void dump_htable(FILE *fp, const char *tag, const htable h)
形式的函数。该函数将结构内容的诊断转储打印到给定文件(通常为stdout
,但有时为stderr
或日志文件),在信息前加上tag
,以便你可以告诉输出来自转储功能的特定调用。该函数也可以进行基本验证 - 例如,它应该确保给出的指针不为空(尽管它会打印出来),如果指针不为空,应该清楚地只检查结构的内容。您可以在创建哈希表后立即调用此函数,并在每次插入操作后再次调用此函数。这将允许您检查代码是否按预期工作。
将功能保留在代码中;确保它是常规编译的(因此它不会过时)并在遇到哈希表问题时使用它。
#ifndef HTABLE_H_INCLUDED
#define HTABLE_H_INCLUDED
struct htablerec {
char **key;
int *frequencies;
int num_keys;
int capacity;
};
typedef struct htablerec *htable;
extern int htable_insert(htable h, char *str);
extern htable htable_new(unsigned size);
extern int htable_search(htable h, char *str);
extern void htable_free(htable h);
#endif /* HTABLE_H_INCLUDED */
#include "htable.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static void *emalloc(size_t size)
{
void *space = malloc(size);
if (space == 0)
{
fprintf(stderr, "Failed to allocate %zu bytes of memory\n", size);
exit(EXIT_FAILURE);
}
return space;
}
static unsigned int htable_word_to_int(const char *word)
{
unsigned int result = 0;
while (*word != '\0')
{
result = (*word++ + 31 * result);
}
return result;
}
htable htable_new(unsigned size)
{
htable h = emalloc(sizeof(*h));
size_t nbytes = size * sizeof(*h->key);
h->key = emalloc(nbytes);
memset(h->key, '\0', nbytes);
h->frequencies = emalloc(size * sizeof(*h->frequencies));
h->capacity = size;
h->num_keys = 0;
return h;
}
void htable_free(htable h)
{
if (h != 0)
{
free(h->frequencies);
free(h->key);
free(h);
}
}
int htable_insert(htable h, char *str)
{
int i;
unsigned int index = htable_word_to_int(str);
int remainder = index % h->capacity;
for (i = 0; i < h->capacity; i++)
{
/* 1. No string at this position */
if (h->key[remainder] == NULL)
{
char *key = emalloc(strlen(str) + 1);
strcpy(key, str);
h->key[remainder] = key;
h->frequencies[remainder] = 1;
h->num_keys++;
return 1;
}
/* 2. the same string is already there */
if (strcmp(str, h->key[remainder]) == 0)
{
h->frequencies[remainder]++;
return h->frequencies[remainder];
}
/* 3. Keep searching */
if (remainder >= h->capacity - 1)
remainder = 0;
else
remainder++;
}
/* No match and no empty spaces left - hash table is full */
return 0;
}
int htable_search(htable h, char *str)
{
unsigned int index = htable_word_to_int(str);
int remainder = index % h->capacity;
for (int i = 0; i < h->capacity; i++)
{
if (h->key[remainder] == NULL)
return -1; /* Definitively not present */
if (strcmp(str, h->key[remainder]) == 0)
return remainder; /* Definitively present */
if (remainder >= h->capacity - 1)
remainder = 0;
else
remainder++;
}
/* Table's full and key not found */
return -1;
}
#include "htable.h"
#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
static void dump_htable(FILE *fp, const char *tag, const htable h)
{
fprintf(fp, "HASHTABLE: %s (0x%" PRIXPTR "\n", tag, (uintptr_t)h);
if (h != 0)
{
fprintf(fp, "Capacity: %d; Number of keys: %d\n", h->capacity, h->num_keys);
fprintf(fp, "Keys: 0x%" PRIXPTR "; Freq: 0x%" PRIXPTR "\n",
(uintptr_t)h->key, (uintptr_t)h->frequencies);
assert(h->key != 0 && h->frequencies != 0);
if (h->num_keys > 0)
{
for (int i = 0; i < h->capacity; i++)
{
if (h->frequencies[i] != 0)
{
assert(h->key[i] != 0);
fprintf(fp, "%3d: %2d %s\n", i, h->frequencies[i], h->key[i]);
}
}
}
}
fflush(fp);
}
int main(void)
{
htable h = htable_new(113);
char word[256];
char op;
/*We must have a space before the %c*/
while(2 == scanf(" %c %255s", &op, word))
{
if ('+' == op)
{
if (htable_insert(h, word) <= 0)
printf("Error: failed to insert %s\n", word);
else
dump_htable(stdout, word, h);
}
else if ('?' == op)
printf("%d %s\n", htable_search(h, word), word);
else
printf("Bogus: %c %s\n", op, word);
}
htable_free(h);
return EXIT_SUCCESS;
}
哈希表的最后一次转储 - 用于检查 - 和结果。
HASHTABLE: unloaded (0x10F100910
Capacity: 113; Number of keys: 50
Keys: 0x10F100930; Freq: 0x10F100CC0
2: 1 wakes
7: 1 necrosis
8: 1 galleries
9: 1 Russia
10: 1 Georges
11: 1 outright
13: 1 brokers
16: 1 factoring
17: 1 keypad
18: 1 Latinizers
19: 1 rhythmically
20: 1 binders
27: 1 sociable
30: 1 Riemannian
33: 1 gentler
38: 1 segregation
39: 1 invalidity
43: 1 snowily
47: 1 cupful
48: 1 zebras
49: 1 Capet
50: 1 dominating
51: 1 unloaded
52: 1 unsound
53: 1 revocable
54: 1 tied
58: 1 combed
59: 1 leadings
60: 1 bran
61: 1 contented
62: 1 sequences
64: 1 replaced
69: 1 escorted
70: 1 infringing
71: 1 onslaught
72: 1 tiring
75: 1 screamer
80: 1 admire
84: 1 build
87: 1 Ottawa
92: 1 Malawi
93: 1 kidded
94: 1 files
95: 1 disconnects
96: 1 puzzles
97: 1 attendances
103: 1 diversification
104: 1 digressed
111: 1 swarthy
112: 1 thickness
-1 insincere
-1 constants
-1 unordered
-1 Toland
-1 butterfly
-1 suburban
-1 overtone
-1 Hauser
-1 numbers
-1 disadvantageous
-1 saintly
-1 Dutton
-1 homomorphic
-1 corporation
-1 climaxes
-1 dietitian
-1 manifestly
-1 greyest
-1 challenge
-1 tentacle
-1 Bernice
-1 bottle
-1 involve
-1 resisted
-1 wholesale
-1 trustworthiness
-1 Poole
-1 fourfold
-1 relentlessly
-1 fittingly
-1 doctorates
-1 cowlick
-1 Missoula
-1 curtsy
-1 calmness
-1 reallocate
-1 bossed
-1 scarce
-1 catheters
-1 regained
-1 autographing
-1 unobservable
-1 apprise
-1 lancer
-1 chicken
-1 crunches
-1 scrambled
-1 reared
-1 pealing
-1 violate
27 sociable
8 galleries
9 Russia
75 screamer
112 thickness
58 combed
69 escorted
53 revocable
104 digressed
92 Malawi
70 infringing
71 onslaught
94 files
93 kidded
52 unsound
54 tied
87 Ottawa
96 puzzles
84 build
7 necrosis
80 admire
47 cupful
13 brokers
38 segregation
49 Capet
10 Georges
60 bran
20 binders
48 zebras
61 contented
17 keypad
43 snowily
64 replaced
50 dominating
11 outright
18 Latinizers
39 invalidity
2 wakes
103 diversification
30 Riemannian
59 leadings
19 rhythmically
33 gentler
111 swarthy
95 disconnects
16 factoring
62 sequences
72 tiring
97 attendances
51 unloaded