【问题标题】:C++ Hashtable issues with rehash重新哈希的 C++ 哈希表问题
【发布时间】:2018-08-01 23:59:38
【问题描述】:

至于我的学校作业,当它达到 %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) "我用 const static 创建了它。我必须这样做,因为否则它不会让我这样做" 当然它不会让你这样做 - 数组必须有它们的编译时已知的大小。在分配有关数组的任务之前,应该已经向您解释了这一点。 2) 为避免此类限制,请考虑使用std::vector。或者,或者,如果您由于某种原因不能使用它 - 动态数组。 3)如果您将数组大小固定,我认为没有理由在所述数组内动态创建items。特别是,由于您的 hash_table 没有释放内存,这会导致内存泄漏。

标签: c++ hashtable


【解决方案1】:

一般来说,要让一个数组更大,你需要做一个更大的数组,并将旧数组的内容复制到新数组中。你想通了!

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

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

如果你在上面将tableSize设为一个变量,并使初始数组更像这样

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

那么你成功的机会就更大了!既然是学校的练习题,给你写代码是不对的……

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-21
    • 2021-02-13
    • 1970-01-01
    • 2012-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多