次のようなキー/値を含む巨大なテキスト ファイル (50 MB) があります。
...
ham 2348239
hehe 1233493
hello 1234213
hello 1812394
hello 1923943
help 2038484
helping 2342394
hesitate 1298389
...
基本的に、それは多くの単語であり、値はフィクション小説全体を含む別のファイル内のその単語の位置へのポインターです。
課題は、すべての文字の組み合わせ AAA ~ ZZZ のハッシュ テーブル インデックスを作成し、それをファイルに格納することによって、非常に高速な検索アルゴリズムを作成することです。ハッシュ値は、その 3 文字で始まる単語の最初の出現を指す必要があります。組み合わせHEH
は を指す必要がhehe
ありHEL
、最初のものhello
などを指す必要があります。
したがって、 を検索するとhelp
、HEL
がハッシュされ、最初の へのポインタが返さhello
れます。ハッシュ テーブルで次のインデックスを検索すると、 へのポインタが取得されるためhesitate
、 で始まる単語の範囲全体にアクセスできますHEL
。
範囲内の単語を見つけるためhelp
に、割り当ては二分探索を行うことを提案します。
私は実際にこれを解決することができましたが、上記のテキスト ファイルが原因で、解決策は非常に醜いものでした。
キー/値のテキスト ファイルを構造化するためのよりエレガントな方法があるに違いないと考えていました。おそらくバイナリです。
アドバイスをいただければ幸いです。
編集
不明確な質問で申し訳ありません。コミュニティからの意見が欲しかっただけです...おそらく、この問題を解決するためのベストプラクティスのアドバイスです。
私のhashTableを構築するコードは次のとおりです。
while ((fscanf(indexFile, "%s %lu\n%n", buf, &bookPos, &rowLength)) != EOF){
newHash = calcHashIndex(buf);
if (curHash < newHash){
curHash++;
indexPos = ftell(indexFile) - rowLength;
for (;curHash <= newHash; curHash++){
hashTable[curHash] = indexPos;
}
curHash = newHash;
}
}
fwrite(hashTable, sizeof(hashTable), 1, hashTableFile);
indexFile でバイナリ検索を実行するコードは次のとおりです。実際にはうまくいきません... 1 回しか出現しないランダムな単語の中には、一致として返されないものがあります。
int binarySearch(unsigned char *searchWord, FILE * file, long firstIndex, long lastIndex){
unsigned char buf[WORD_LEN];
long bookPos, middle;
int cmpVal, rowLength;
while (firstIndex < lastIndex){
middle = (firstIndex + lastIndex)/2;
fseek(file, middle, SEEK_SET);
goBackToLastNewLine(file, 0);
fscanf(file, "%s %lu\n%n", buf, &bookPos, &rowLength);
if (strcmp(searchWord, buf) <= 0){
lastIndex = ftell(file) - rowLength;
} else {
firstIndex = ftell(file);
}
}
fseek(file, -rowLength, SEEK_CUR);
return (strcmp(searchWord, buf) == 0) ? 1 : 0;
}