英文:
Testing Hash Table
问题
I've translated the code part as you requested:
我需要测试我的哈希表是否正常工作,但测试失败,因为我的哈希表似乎找不到任何元素。编译器没有问题,调试器也没有问题,问题应该出在代码逻辑中。我认为问题可能在insert()函数中,但我已经尝试多次更改它,但没有帮助。请你查看一下代码,告诉我可能出了什么问题?
控制台显示如下:
我的哈希表:
时间:0.610612,在插入后:270717,在擦除后:270717,找到:0
STL无序映射:
时间:0.67032,在插入后:316124,在擦除后:115991,找到:115884
:(
我认为问题的根本在于insert(),因为它是首个崩溃的地方。此外,这是测试代码,但应该没问题,因为它是专门用于测试的。
Let me know if you need anything else.
英文:
I need to test if my hash table works right, but it fails the test as my hash table doesn't seem to find any elements. No problems in compiler, neither through debugger, it's somewhere in the logic of the code. I thought it's because of insert() function, but it seems ok to me, as I tried changing it times again, but nothing helped. Can you look through the code and tell me what can be wrong with it please?
Here's what console shows me:
My HashTable:
Time: 0.610612, after insert: 270717, after erase:270717, found: 0
STL unordered_map:
Time: 0.67032, after insert: 316124, after erase: 115991, found: 115884
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <unordered_map>
using namespace std;
const int M = 10000;
const double MAX_LOAD_FACTOR = 0.75;
long long generateRandLong() {
int numDigits = rand() % 19 + 10; // Random number of digits between 10 and 19
unsigned long long num = rand() % 9 + 1; // Random non-zero first digit
for (int i = 1; i < numDigits; i++) {
unsigned long long digit = rand() % 10;
num = num * 10 + digit;
}
return num % (unsigned long long)(pow(10, 18));
}
string generateRandColor() {
string colors[] = { "black", "white", "gold", "rose gold", "silver" };
return colors[rand() % 5];
}
struct Data {
long long key;
long long number;
string color;
bool is_charger;
Data() {
key = generateRandLong();
number = rand() % 10000 + 1;
color = generateRandColor();
is_charger = rand() % 2;
}
};
struct HashNode {
long long key;
Data data;
HashNode* next;
HashNode* prev; //doubly
// constructor
HashNode(Data data) {
this->key = data.key;
this->data = data;
next = nullptr;
prev = nullptr;
}
HashNode(long long k, Data v) : key(k), data(v), next(nullptr) {}
};
struct LinkedList {
HashNode* head = nullptr;
HashNode* tail = nullptr;
int size = 0;
~LinkedList() {
clear();
}
void push_front(HashNode* newHashNode) {
//head->prev = newNode; //doubly
head = newHashNode;
if (tail == nullptr) {
tail = newHashNode;
}
size++;
}
HashNode* getHead() {
return head;
}
void clear() {
HashNode* current = head;
while (current != nullptr) {
HashNode* next = current->next;
delete current;
current = next;
}
head = nullptr;
tail = nullptr;
size = 0;
}
bool remove(long long key) {
if (head == nullptr) {
return false;
}
if (head->data.key == key) {
HashNode* temp = head;
head = head->next;
delete temp;
size--;
return true;
}
HashNode* current = head;
while (current->next != nullptr && current->next->data.key != key) {
current = current->next;
}
if (current->next == nullptr) {
return false;
}
HashNode* temp = current->next;
current->next = temp->next;
if (temp == tail) {
tail = current;
}
delete temp;
size--;
return true;
}
bool search(long long key) {
HashNode* current = head;
while (current != nullptr) {
if (current->data.key == key) {
return true;
}
current = current->next;
}
return false;
}
};
struct HashTable {
LinkedList* bucketsArray;
int bucketCount;
bool isEmpty = true;
int uniqueKeyCount = 0;
float MAX_LOAD_FACTOR;
// Hash function for long long keys
int hash(long long key) {
return key % bucketCount;
}
HashTable(int initialBucketCount, float MAX_LOAD_FACTOR) {
bucketCount = initialBucketCount;
this->MAX_LOAD_FACTOR = MAX_LOAD_FACTOR;
bucketsArray = new LinkedList[bucketCount];
}
~HashTable() {
delete[] bucketsArray;
}
void rehash() {
int oldBucketCount = bucketCount;
bucketCount *= 2;
LinkedList* newBucketsArray = new LinkedList[bucketCount];
uniqueKeyCount = 0;
for (int i = 0; i < oldBucketCount; i++) {
HashNode* current = bucketsArray[i].getHead();
while (current != nullptr) {
HashNode* newNode = new HashNode(current->data);
int bucketIndex = hash(current->data.key);
newBucketsArray[bucketIndex].push_front(newNode);
uniqueKeyCount++;
current = current->next;
}
}
delete[] bucketsArray;
bucketsArray = newBucketsArray;
}
void insert(long long key, Data value) {
int bucketIndex = hash(key);
HashNode* current = bucketsArray[bucketIndex].getHead();
while (current != nullptr) {
if (current->data.key == key) {
current->data = value;
return;
}
current = current->next;
}
HashNode* newHashNode = new HashNode(key, value);
bucketsArray[bucketIndex].push_front(newHashNode);
uniqueKeyCount++;
double loadFactor = (double)uniqueKeyCount / bucketCount;
if (loadFactor > MAX_LOAD_FACTOR) {
rehash();
}
}
bool erase(long long key) {
int bucketIndex = hash(key);
bool found = bucketsArray[bucketIndex].remove(key);
if (found) {
uniqueKeyCount--;
float loadFactor = (float)uniqueKeyCount / bucketCount;
if (loadFactor < MAX_LOAD_FACTOR / 2) {
rehash();
}
}
return found;
}
bool find(long long key) {
int bucketIndex = hash(key);
return bucketsArray[bucketIndex].search(key);
}
int size() {
int count = 0;
for (int i = 0; i < bucketCount; i++) {
LinkedList& bucket = bucketsArray[i];
HashNode* current = bucket.getHead();
while (current != nullptr) {
count++;
current = current->next;
}
}
return count;
}
};
I think the origin problem is in insert() coz it's the first one which crashes. Also, here's the test code, but it should be right, as it was given to me for the testing specifically.
bool testHashTable()
{
const int iters = 500000;
const int keysAmount = iters * 1;
// generate random keys:
long long* keys = new long long[keysAmount];
long long* keysToInsert = new long long[iters];
long long* keysToErase = new long long[iters];
long long* keysToFind = new long long[iters];
for (int i = 0; i < keysAmount; i++)
{
keys[i] = generateRandLong();
}
for (int i = 0; i < iters; i++)
{
keysToInsert[i] = keys[generateRandLong() % keysAmount];
keysToErase[i] = keys[generateRandLong() % keysAmount];
keysToFind[i] = keys[generateRandLong() % keysAmount];
}
// test my HashTable:
HashTable hashTable(500000, 0.75);
clock_t myStart = clock();
for (int i = 0; i < iters; i++)
{
hashTable.insert(keysToInsert[i], Data());
}
int myInsertSize = hashTable.size();
for (int i = 0; i < iters; i++)
{
hashTable.erase(keysToErase[i]);
}
int myEraseSize = hashTable.size();
int myFoundAmount = 0;
for (int i = 0; i < iters; i++)
{
if (hashTable.find(keysToFind[i]))
{
myFoundAmount++;
}
}
clock_t myEnd = clock();
float myTime = (float(myEnd - myStart)) / CLOCKS_PER_SEC;
// test STL hash table:
unordered_map<long long, Data> unorderedMap;
clock_t stlStart = clock();
for (int i = 0; i < iters; i++)
{
unorderedMap.insert({keysToInsert[i], Data()});
}
int stlInsertSize = unorderedMap.size();
for (int i = 0; i < iters; i++)
{
unorderedMap.erase(keysToErase[i]);
}
int stlEraseSize = unorderedMap.size();
int stlFoundAmount = 0;
for (int i = 0; i < iters; i++)
{
if (unorderedMap.find(keysToFind[i]) != unorderedMap.end())
{
stlFoundAmount++;
}
}
clock_t stlEnd = clock();
float stlTime = (float(stlEnd - stlStart)) / CLOCKS_PER_SEC;
cout << "My HashTable:" << endl;
cout << "Time: " << myTime << ", after insert: " << myInsertSize << ", after erase: " << myEraseSize << ", found: " << myFoundAmount << endl;
cout << "STL unordered_map:" << endl;
cout << "Time: " << stlTime << ", after insert: " << stlInsertSize << ", after erase: " << stlEraseSize << ", found: " << stlFoundAmount << endl << endl;
delete[] keys;
delete[] keysToInsert;
delete[] keysToErase;
delete[] keysToFind;
if (myInsertSize == stlInsertSize && myEraseSize == stlEraseSize && myFoundAmount == stlFoundAmount)
{
cout << "The lab is completed" << endl;
return true;
}
cerr << ":(" << endl;
return false;
}
int main() {
srand(time(NULL));
testHashTable();
return 0;
}
答案1
得分: 1
这是你要的翻译:
这是你要做的:编写一个函数,检查哈希表中的数据结构是否一致,并打印哈希表的完整内容。在每次更改哈希表的操作之后调用该函数。然后运行你的测试。
要么你找到损坏哈希表的操作,要么你从正确的哈希表 -> 操作 -> 崩溃。在这种情况下,使用调试器,并在崩溃函数上设置断点。
英文:
Here’s what you do: You write a function that checks whether the dat structures in your hash table are consistent, and prints the complete contents of the hash table. You call that after every operation that changes the hash table. And then you run your tests.
Either you find the operation that messed up your table, or you go from correct table -> operation -> crash. In that case use the debugger and set a breakpoint on the crashing function.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论