在哈希表中调整字符串数组的大小

Resizing string array in hash-table

本文关键字:数组 字符串 哈希表 调整      更新时间:2023-10-16

我现在正在学习哈西。当填充> = 80%时,我正在尝试调整哈希表的大小。但是,每当我尝试调整大小时,我都会得到不确定的行为或崩溃。

我试图制作一个带有更多字段的新字符串数组,然后删除了旧字段,但这不起作用。

Hashtable.h


class hashtable
{
    public:
        hashtable();
        void insert(string);
        void resize_array();
        int hashfunction(string str);
        string* getArray();
    private:
         int elemts_in_array;
         int table_size;
         string* T;
};

hashtable.cpp

hashtable::hashtable()
{
    // your code (start with a capacity of 10)
    table_size = 10;
    elemts_in_array = 0;
    string *array = new string[table_size];
    T = array;
}

void hashtable::insert(string key)
{
    string* array = getArray();
    int hkey=hashfunction(key);
    float filled = float(elemts_in_array)/float(table_size);
// When the array is more than 80% filled resize it and double the table_size
    if(filled >= 0.8)
    {
        cout << "Resizing Array.." << endl;
        resize_array();
    }
    for(int i=0; i<table_size;i++)
    {
// if the field is empty insert it, else go +1
        if(array[(hkey+i)%table_size] == "")
        {
            array[(hkey+i)%table_size] = key;
            elemts_in_array++;
            break;
        }
        if(array[(hkey+i)%table_size] == key)
        {
          // it is the same element
            break;
        }
    }
}

void hashtable::resize_array()
{
    int old_table_size =table_size;
    table_size*=2; // double the size of the hashtable
    string* old_array= new string[table_size]; // save the old array entries
    old_array = T;
// Apply the old entries in old_array
    for(int i=0; i<table_size;i++)
    {
        old_array[i]= T[i];
    }
//create a new array with double size
    string *new_array = new string[table_size];
//delete the old T
    delete[] T;
    T = new_array;
//re-hash the old entries into the new array with double size (HERE I GOT THE ISSUES)
    for(int i=0; i<table_size/2; i++)
    {
        insert(old_array[i]);
    }
}

有时我的程序进入循环或崩溃。我真的不知道为什么它不起作用。

如果您使用调试器逐步执行程序,则可能会发现resize_array函数的问题。

将旧表条目复制回新分配的数组时,它使用insert函数。这有一些问题:

  1. 由于碰撞分辨率,您可能不会恢复原始值的相同顺序;
  2. insert功能增加了表尺寸,因此它最终会认为它的条目是您最初插入的两倍。

现在,崩溃可能发生,因为insert将再次触及桌面限制。周期重复直到您要么堆叠溢出或用尽内存。

在您的字符串中复制的正确方法是:

for(int i = 0; i < table_size / 2; i++)
{
    T[i] = old_array[i];
}

但是,在任何事情发生之前,还有另一个问题可能会崩溃。您首先保存了您的价值:

for(int i=0; i<table_size;i++)
{
    old_array[i]= T[i];
}

请注意,table_size已经加倍,因此您将访问T的末尾。您应该改用old_table_size上的循环。

您还需要一些不必要的复制。如果要重新分配T,那就这样做:

void hashtable::resize_array()
{
    int old_table_size = table_size;
    table_size *= 2;
    string* old_T = T;
    T = new string[table_size];
    for (int i = 0; i < old_table_size; i++)
    {
        std::swap(T[i], old_T[i]);   // or in C++11 assign with std::move
    }
    delete[] old_T;
}