C ++哈希表与重新哈希问题

时间:2018-08-01 23:59:38

标签: c++ hashtable

至于我的学校任务,当它达到%70-90负载时,我必须更新哈希表大小。我在重新哈希表时遇到问题。我无法修改tableSize(因为我使用const static创建了它。我不得不这样做是因为它不会让我失望)。我也不能修改HashTable,因为它不是可修改的值。我认为我的构造函数是错误的,但我无法自行确定。

感谢您的帮助。

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

1 个答案:

答案 0 :(得分:1)

通常,要使数组更大,您需要使数组更大,然后将旧数组的内容复制到新数组中。你想通了!

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

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

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

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

那么您就有更大的成功机会!由于这是一次学校练习,因此不适合为您编写代码...

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