我正在尝试制作一个可以在非常大的哈希表(超过100万个条目)上工作的rehashing函数,而且我当前的方法效率非常低。这是我的结构
typedef struct {
int id, count, correct, valid;
char* word;
} Entry;
typedef struct {
Entry* arr;
int size, numValid;
} Hash;
以下是它现在的功能(非常慢,不使用memcpy):
void rehash(Hash* hash) {
Entry* tempArr;
int i;
tempArr = calloc(hash->size, sizeof(Entry));
for(i = 0; i < hash->size; i++) {
if(hash->arr[i].count) {
tempArr[i].count = hash->arr[i].count;
tempArr[i].correct = hash->arr[i].valid;
tempArr[i].word = malloc(strlen(hash->arr[i].word) + 1);
strcpy(tempArr[i].word,hash->arr[i].word);
tempLen++;
}
memcpy(&tempArr[i],&hash->arr[i],sizeof(Entry));
tempArr[i] = hash->arr[i];
}
removeAllEntries(hash);
resize(hash);
for(i = 0; i < (hash->size / 2); i++) {
if(tempArr[i].count > 0) {
addEntry(hash,tempArr[i].word,tempArr[i].count);
/*printf("Added %s with count %d\n",tempArr[i].word,tempArr[i].count);*/
free(tempArr[i].word);
}
}
free(tempArr);
}
我更喜欢使用memcpy,但我不能为我的生活让它正常工作。这是我正在尝试的(这是不起作用的代码,以及我正在寻求帮助的代码):
void rehash(Hash* hash) {
Entry* tempArr;
int i;
tempArr = calloc(hash->size, sizeof(Entry));
fprintf(stderr,"size: %d\n",hash->size * sizeof(Entry));
memcpy((tempArr),(hash->arr),hash->size * sizeof(Entry));
removeAllEntries(hash);
resize(hash);
for(i = 0; i < (hash->size / 2); i++) {
if(tempArr[i].count > 0) {
addEntry(hash,tempArr[i].word,tempArr[i].count);
/*printf("Added %s with count %d\n",tempArr[i].word,tempArr[i].count);*/
free(tempArr[i].word);
}
}
free(tempArr);
}
我确信这是一个简单的单行修复,但我无法让自己看到它。
void addEntry(Hash* hash, char* tag, int count) {
int value = CHV(hash->size, tag), flag = 1, iter = 0;
int possIndex = findEntry(hash, tag);
/*fprintf(stderr,"AddEntry...\n");*/
if(possIndex >= 0) {
(hash->arr[possIndex].count)++;
return;
}
if((hash->size - hash->numValid) < ((double)hash->size / 10))
{
rehash(hash);
}
while(flag) {
iter++;
if(!(hash->arr[value].valid)) {
hash->arr[value].word = calloc(strlen(tag) + 1, sizeof(char));
strcpy(hash->arr[value].word, tag);
wordsAlloced++;
hash->arr[value].valid = 1;
hash->arr[value].correct = 1;
hash->arr[value].count = count;
flag = 0;
}
else {
value++;
if(value == hash->size) {
value = 0;
}
}
}
hash->numValid++;
}
答案 0 :(得分:1)
我认为memcpy没问题。问题是免费的所有条目removeAllEntries(hash);
然后tempArr[i].word
是free
中的双free(tempArr[i].word);
因为它是复制指针。在tempArr[i].word
中使用addEntry(hash,tempArr[i].word,tempArr[i].count);
也无效。它已经free
'd。
一种解决方案建议使用realloc
。
替换
void resize(Hash* hash) {
free(hash->arr);
hash->size *= 2;
hash->arr = calloc(hash->size, sizeof(Entry));
//TOTALALLOC += (hash->size * sizeof(Entry));
}
与
void resize(Hash* hash) {
Entry* tempArr;
if((tempArr = realloc(hash->arr, 2 * hash->size * sizeof(Entry)))==NULL){
fprintf(stderr,"failed realloc in resize.\n");
return ;
}
hash->size *= 2;
hash->arr = tempArr;
//TOTALALLOC += (hash->size * sizeof(Entry));
}
不会重新调整目的。
另一种解决方案
如果出于某种原因需要进行重组。改变以下
void rehash(Hash* hash) {
Entry* tempArr;
int i;
tempArr = malloc(hash->size * sizeof(Entry));//Initialization isn't required because it is replaced by memcpy.
//fprintf(stderr,"size: %d\n",hash->size * sizeof(Entry));
memcpy(tempArr,hash->arr, hash->size * sizeof(Entry));
//To replicate word
for(i = 0; i < hash->size; i++) {
if(hash->arr[i].count) {
tempArr[i].word = malloc(strlen(hash->arr[i].word) + 1);
strcpy(tempArr[i].word, hash->arr[i].word);
}
}
removeAllEntries(hash);
resize(hash);
for(i = 0; i < (hash->size / 2); i++) {
if(tempArr[i].count > 0) {
addEntry(hash,tempArr[i].word, tempArr[i].count);
/*printf("Added %s with count %d\n",tempArr[i].word,tempArr[i].count);*/
free(tempArr[i].word);
}
}
free(tempArr);
}
如果numValid
代表有效的注册号,我认为只保存word
和count
就足够了。