使用rehash的C++哈希表问题

C++ Hashtable issues with rehash

本文关键字:哈希表 问题 C++ rehash 使用      更新时间:2023-10-16

至于我的学校作业,当它达到%70-90负载时,我必须更新我的哈希表大小。我在重新哈希表方面遇到了问题。我无法修改tableSize(因为我用const-static创建了它。我不得不修改,因为它不允许我这样做(。我也不能修改哈希表,因为它是不可修改的值。我认为我的构造器是错的,但我不能自己弄清楚。

感谢您的帮助。

hash_table.cpp

#include <iostream>
#include <cstdlib>
#include <string>
#include "hash_table.h"
using namespace std;

hash_table::hash_table()
{
for (int i = 0; i < tableSize; i++) {
HashTable[i] = new item;
HashTable[i]->name = "";
HashTable[i]->info.documentName = "";
HashTable[i]->info.count = 1;
HashTable[i]->info.next = NULL;
HashTable[i]->next = NULL;
}
}
int hash_table::Hash(string key)
{
int hash = 0;
int index;
for (int i = 0; i < key.length(); i++) {
hash = (hash + (int)key[i]) * 17;
}
index = hash % tableSize;
return index;
}
void hash_table::AddItem(string name,string document)
{
int index = Hash(name);
int check = size / tableSize;
if(check > 0.78){
reHash();
}
if (HashTable[index]->name == "") {
HashTable[index]->name = name;
HashTable[index]->info.documentName = document;
HashTable[index]->info.count = 1;
size++;
}
else if (HashTable[index]->name == name) {
if (HashTable[index]->info.documentName == document) {
HashTable[index]->info.count++;
}
else if (HashTable[index]->info.next != NULL) {
Document* checkPtr = &HashTable[index]->info;
while (HashTable[index]->info.next != NULL) {
checkPtr = checkPtr->next;
if (checkPtr != NULL) {
if (checkPtr->documentName == document) {
checkPtr->count++;
}
}
else {
break;
}
}
}
else {
Document* tempPtr = &HashTable[index]->info;
Document* t = new Document;
t->documentName = document;
t->count = 1;
t->next = NULL;
while (tempPtr->next != NULL) {
tempPtr = tempPtr->next;
}
tempPtr->next = t;
}
}
else {
item* Ptr = HashTable[index];
item* n = new item;
n->name = name;
n->next = NULL;
while (Ptr->next != NULL) {
Ptr = Ptr->next;
}
Ptr->next = n;
}
}
int hash_table::NumberOfItemsInIndex(int index)
{
int count = 0;
if (HashTable[index]->name == "") {
return count;
}
else {
count++;
item* Ptr = HashTable[index];
while (Ptr->next != NULL) {
count++;
Ptr = Ptr->next;
}
}
return count;
}
void hash_table::PrintTable() // CAN USE AS CALCULATING TOTAL NUMBER
{
int number;
for (int i = 0; i < tableSize; i++) {
number = NumberOfItemsInIndex(i);
cout << "----------------" << endl;
cout << "index = " << i << endl;
cout << HashTable[i]->name << endl;
cout << HashTable[i]->info.count << endl;
cout << "# of items = " << number << endl;
cout << "----------------" << endl;
}
}
void hash_table::PrintItemsInIndex(int index)
{
item* Ptr = HashTable[index];
if (Ptr->name == "empty") {
cout << "index = " << index << " is empty" << endl;
}
else {
cout << "index " << index << "countains the following item" << endl;
while (Ptr != NULL) {
cout << "--------------" << endl;
cout << Ptr->name << endl;
cout << Ptr->info.count << endl;
cout << "--------------" << endl;
Ptr = Ptr->next;
}
}
}
void hash_table::FindString(string name)
{
int index = Hash(name);
bool foundQuery = false;
item *Ptr = HashTable[index];
Document* checkPtr = NULL;
while (Ptr != NULL) {
if (Ptr->name == name) {
foundQuery = true;
checkPtr = &Ptr->info;
}
Ptr = Ptr->next;
}
if (foundQuery == true) {
while (checkPtr != NULL) {
cout << "in document " << checkPtr->documentName << ", " << name << " found " << checkPtr->count << " times." << endl;
checkPtr = checkPtr->next;
}
}
else {
cout << "No document contains the given query" << endl;
}
}
void hash_table::reHash()
{
int oldCapacity = tableSize;
tableSize = tableSize * 2 + 1;
item** newHashTable = new item*[tableSize];
for (int i = 0; i < oldCapacity; i++) {
item *n = HashTable[i];
while (n != NULL) {
item *tmp = n;
n = n->next;
item*& bucket = newHashTable[hash_table::Hash(tmp->name) % tableSize];
tmp->next = bucket;
bucket = tmp;
}
}
delete[] HashTable;
HashTable = newHashTable;
}

hash_table.h

#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
#ifndef HASH_H
#define HASH_H
struct Document {
string documentName;
int count;
Document* next;
};
struct item {
string name;
item* next;
struct Document info;
};


class hash_table{
private:
const static int tableSize = 26;
item* HashTable[tableSize];
public:
hash_table();
int Hash(string key);
void AddItem(string name, string document);
int NumberOfItemsInIndex(int index);
void PrintTable();
void PrintItemsInIndex(int index);
void FindString(string name);
void reHash();
int size = 0;
};
#endif  // !HASH_H

通常,要使数组变大,需要制作一个更大的数组,并将旧数组的内容复制到新数组。你想通了!

通过将table_size设为常量,然后在此处声明一个固定大小的数组,可以将您锁定为固定的数组大小。

const static int tableSize = 26;
item* HashTable[tableSize];

如果您将tableSize设置为上面的一个变量,并使初始数组更像这个

item** newHashTable = new item*[tableSize];

那么你成功的机会就大了!既然这是一个学校练习,为你做代码是不对的。。。

不过,一般来说,在程序执行期间需要更改数组大小的情况下,使用向量要好得多。这些可以在执行过程中随意扩展,非常值得阅读和做一些例子。