使用哈希数组对罗密欧与朱丽叶文本进行统计分析。我差了 3684 个字中的 2 个字
Using a Hash Array to statistically analyze Romeo and Juliet text. I am off by 2 words out of 3684
所以罗密欧与朱丽叶中使用的唯一单词的数量应该是3648。我得到3682。我已经尽可能地调试并重写了更新功能。 class 的老师和其他学生也得到了 3648。所以基本上我差了 2。
问题出在更新函数中,该函数将密钥输入哈希数组,检查冲突等。只要有新条目,它就会更新大小。
这是我粘贴在 hastebin 中的代码:http://hastebin.com/irawafeyen.avrasm
这是粘贴在 hastebin 中的罗密欧与朱丽叶的文本:http://hastebin.com/semuponata.hs
为了使我的代码 运行,您必须将文件另存为 RomeoAndJuliet.txt 与代码
在同一文件夹中
为了方便起见,这里粘贴了我的代码。
#define HASHSIZE 4001
#define ARRAY_SIZE 23868
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
// Use folding on a string, summed 4 bytes at a time
int sfold(const char* key)
{
unsigned int *lkey = (unsigned int *)key;
int intlength = strlen(key)/4;
unsigned int sum = 0;
for(int i=0; i<intlength; i++)
sum += lkey[i];
// Now deal with the extra chars at the end
int extra = strlen(key) - intlength*4;
char temp[4];
lkey = (unsigned int *)temp;
lkey[0] = 0;
for(int i=0; i<extra; i++)
temp[i] = key[intlength*4+i];
sum += lkey[0];
return sum % HASHSIZE;
}
class HashArray
{
struct Node
{
string word;// = "null";
int frequency;
};
private:
int size;
public:
Node hasharr[HASHSIZE];
HashArray()
{
for(int i = 0; i < HASHSIZE; i++)
hasharr[i].frequency = 0;
size = 0;
}
~HashArray() {}
void update(string charkey)
{
const char* temp = charkey.c_str();
int intkey = sfold(temp);
if (hasharr[intkey].frequency == 0)
{
hasharr[intkey].word = charkey;
hasharr[intkey].frequency = 1;
size++;
}
else if(hasharr[intkey].word == charkey)
hasharr[intkey].frequency++;
else
{
while(hasharr[intkey].frequency != 0 && hasharr[intkey].word != charkey)
{
if(intkey > 4000)
intkey = 1;
intkey++;
}
if(hasharr[intkey].word == charkey)
hasharr[intkey].frequency++;
else
{
hasharr[intkey].word = charkey;
hasharr[intkey].frequency++;
size++;
}
}
}
void hashsize()
{
cout <<"The amount of entries in the hash table is "<< size;
}
void find1timewords() // prints all words that appear only one and then prints the amount of these types of words.
{
int i = 0;
int count = 0;
while(i < 4000)
{
if(hasharr[i].frequency == 1)
{
cout << endl << i << " ";
cout << hasharr[i].frequency <<" "<< hasharr[i].word<<" ";
count++;
}
i++;
}
cout << " number of words appearing one time: " << count;
}
void printFirstN(int n) // Prints the first N hash entries at indexes 0 thru N.
{
for (int i = 0; i < n; i++)
cout << endl << "tag: " << i << " word: " << hasharr[i].word << " frequency: " << hasharr[i].frequency <<endl;
}
void printTopN(int n) //print the first N most used words.
{
int max;
}
};
int main()
{
HashArray hasharray;
ifstream inputFile;
inputFile.open("RomeoAndJuliet.txt");
string temp;
while(inputFile >> temp)
hasharray.update(temp);
hasharray.hashsize();
//hasharray.printFirstN(25);
//hasharray.find1timewords();
inputFile.close();
cin.get();
}
我认为你有一个 Hash Collision,这意味着两个键产生相同的值。您可能需要更改计算哈希值的方式,或者通过添加哈希冲突函数来捕获两个键生成相同哈希值的实例。
看看this。
您的哈希冲突检查代码超出了哈希数组的末尾。
此代码
while(hasharr[intkey].frequency != 0 && hasharr[intkey].word != charkey)
{
if(intkey > 4000)
intkey = 1;
intkey++;
}
当 intkey
刚好是 4000 时出现问题。由于 intkey++
行,intkey
循环时的值将是 4001。
一个简单的解决方法是在检查越界之前递增。另外,我不明白为什么要从要检查的哈希列表中排除 0,所以当它溢出时将值设置回 0。
while(hasharr[intkey].frequency != 0 && hasharr[intkey].word != charkey)
{
intkey++;
if(intkey > 4000)
intkey = 0;
}
为什么这会使您的代码出错 - 除了 "Undefined Behavior" 在数组边界之外写入,这可能会导致您的代码执行任何操作(它在我的系统上崩溃),如果它确实成功地写入过去数组的末尾,它会将单词添加到单词计数中,但随后将无法在您的哈希中正确找到该单词。
所以罗密欧与朱丽叶中使用的唯一单词的数量应该是3648。我得到3682。我已经尽可能地调试并重写了更新功能。 class 的老师和其他学生也得到了 3648。所以基本上我差了 2。
问题出在更新函数中,该函数将密钥输入哈希数组,检查冲突等。只要有新条目,它就会更新大小。
这是我粘贴在 hastebin 中的代码:http://hastebin.com/irawafeyen.avrasm
这是粘贴在 hastebin 中的罗密欧与朱丽叶的文本:http://hastebin.com/semuponata.hs
为了使我的代码 运行,您必须将文件另存为 RomeoAndJuliet.txt 与代码
在同一文件夹中为了方便起见,这里粘贴了我的代码。
#define HASHSIZE 4001
#define ARRAY_SIZE 23868
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
// Use folding on a string, summed 4 bytes at a time
int sfold(const char* key)
{
unsigned int *lkey = (unsigned int *)key;
int intlength = strlen(key)/4;
unsigned int sum = 0;
for(int i=0; i<intlength; i++)
sum += lkey[i];
// Now deal with the extra chars at the end
int extra = strlen(key) - intlength*4;
char temp[4];
lkey = (unsigned int *)temp;
lkey[0] = 0;
for(int i=0; i<extra; i++)
temp[i] = key[intlength*4+i];
sum += lkey[0];
return sum % HASHSIZE;
}
class HashArray
{
struct Node
{
string word;// = "null";
int frequency;
};
private:
int size;
public:
Node hasharr[HASHSIZE];
HashArray()
{
for(int i = 0; i < HASHSIZE; i++)
hasharr[i].frequency = 0;
size = 0;
}
~HashArray() {}
void update(string charkey)
{
const char* temp = charkey.c_str();
int intkey = sfold(temp);
if (hasharr[intkey].frequency == 0)
{
hasharr[intkey].word = charkey;
hasharr[intkey].frequency = 1;
size++;
}
else if(hasharr[intkey].word == charkey)
hasharr[intkey].frequency++;
else
{
while(hasharr[intkey].frequency != 0 && hasharr[intkey].word != charkey)
{
if(intkey > 4000)
intkey = 1;
intkey++;
}
if(hasharr[intkey].word == charkey)
hasharr[intkey].frequency++;
else
{
hasharr[intkey].word = charkey;
hasharr[intkey].frequency++;
size++;
}
}
}
void hashsize()
{
cout <<"The amount of entries in the hash table is "<< size;
}
void find1timewords() // prints all words that appear only one and then prints the amount of these types of words.
{
int i = 0;
int count = 0;
while(i < 4000)
{
if(hasharr[i].frequency == 1)
{
cout << endl << i << " ";
cout << hasharr[i].frequency <<" "<< hasharr[i].word<<" ";
count++;
}
i++;
}
cout << " number of words appearing one time: " << count;
}
void printFirstN(int n) // Prints the first N hash entries at indexes 0 thru N.
{
for (int i = 0; i < n; i++)
cout << endl << "tag: " << i << " word: " << hasharr[i].word << " frequency: " << hasharr[i].frequency <<endl;
}
void printTopN(int n) //print the first N most used words.
{
int max;
}
};
int main()
{
HashArray hasharray;
ifstream inputFile;
inputFile.open("RomeoAndJuliet.txt");
string temp;
while(inputFile >> temp)
hasharray.update(temp);
hasharray.hashsize();
//hasharray.printFirstN(25);
//hasharray.find1timewords();
inputFile.close();
cin.get();
}
我认为你有一个 Hash Collision,这意味着两个键产生相同的值。您可能需要更改计算哈希值的方式,或者通过添加哈希冲突函数来捕获两个键生成相同哈希值的实例。
看看this。
您的哈希冲突检查代码超出了哈希数组的末尾。 此代码
while(hasharr[intkey].frequency != 0 && hasharr[intkey].word != charkey)
{
if(intkey > 4000)
intkey = 1;
intkey++;
}
当 intkey
刚好是 4000 时出现问题。由于 intkey++
行,intkey
循环时的值将是 4001。
一个简单的解决方法是在检查越界之前递增。另外,我不明白为什么要从要检查的哈希列表中排除 0,所以当它溢出时将值设置回 0。
while(hasharr[intkey].frequency != 0 && hasharr[intkey].word != charkey)
{
intkey++;
if(intkey > 4000)
intkey = 0;
}
为什么这会使您的代码出错 - 除了 "Undefined Behavior" 在数组边界之外写入,这可能会导致您的代码执行任何操作(它在我的系统上崩溃),如果它确实成功地写入过去数组的末尾,它会将单词添加到单词计数中,但随后将无法在您的哈希中正确找到该单词。