【问题标题】:Resizing string array in hash-table在哈希表中调整字符串数组的大小
【发布时间】:2019-10-07 10:29:41
【问题描述】:

我现在正在学习散列。我正在尝试在填充 >=80% 时调整我的哈希表的大小。但是每次我尝试调整它的大小时,我都会得到未定义的行为或崩溃。

我尝试创建一个包含更多字段的新字符串数组,然后我删除了旧的但没有用。

哈希表.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;
};

哈希表.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]);
    }
}

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

【问题讨论】:

  • 最明显的违规者是old_array = T;,然后是delete[] T;,最后是一个循环执行insert(old_array[i]);一旦你delete[] Told_array留下一个悬空指针,钻入它会调用UB。撒盐,您在该函数中也有内存泄漏,因为string* old_array= new... 在下一行泄漏。
  • 哦,嘿嘿,我直接看过去了那个作业,发现了一堆其他问题

标签: c++ hashtable


【解决方案1】:

如果您使用调试器逐步执行程序,您可能会发现 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;
}

【讨论】:

  • 您好,感谢您的回答。我必须用新的大小重新散列旧条目,所以我必须使用插入函数(我认为)和新的表大小。
  • 哦,真的。抱歉,我不应该在编译时回答 SO 问题。我的想法不是100%在这里。你说得对。因此,在这种情况下,不需要复制,但您至少必须在插入之前将包含的元素数重置为零。
猜你喜欢
  • 2012-04-15
  • 1970-01-01
  • 2011-06-24
  • 2013-12-21
  • 1970-01-01
  • 2012-10-14
  • 2015-07-13
  • 1970-01-01
相关资源
最近更新 更多