我正在尝试制作一个rehashing函数,该函数将适用于非常大的哈希表(超过100万个条目),而我目前的方法效率非常低。这是我的结构
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 %dn",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: %dn",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 %dn",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++;
}
我认为memcpy没有问题。问题是removeAllEntries(hash);
释放所有条目,然后tempArr[i].word
是free(tempArr[i].word);
中的双free
,因为它是复制的指针。在addEntry(hash,tempArr[i].word,tempArr[i].count);
中使用tempArr[i].word
也是无效的。已经是free
'd了。
一种解决方案提出使用CCD_ 8。
更换
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: %dn",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 %dn",tempArr[i].word,tempArr[i].count);*/
free(tempArr[i].word);
}
}
free(tempArr);
}
如果numValid
代表有效的注册号,我认为只保存一个word
和count
就足够了。