在散列函数中发生重新散列时,赋值运算符重载不起作用

时间:2016-11-19 14:27:52

标签: c++ segmentation-fault hashtable assignment-operator dynamic-allocation

我正在实现HashMap,我有一个复制构造函数和赋值运算符重载函数。当在HashMap中发生重新散列时,赋值运算符重载函数会引发分段错误。但是,如果没有重新发生,则赋值运算符正常工作。我想我可能已经看了很长时间的代码,如果一组新的眼睛扫描代码,问题会变得很明显。

谢谢

以下是我的主要成员函数:

HashMap::HashMap()
    :hasher{hash}, Buckets_Array{new Node* [initialBucketCount]}, currentBucketCount{initialBucketCount}, sz{0}

{
    fillArray(Buckets_Array, currentBucketCount);


}


HashMap::HashMap(const HashMap& hm)
    :hasher{hm.hasher}, Buckets_Array{new Node*[hm.currentBucketCount]},currentBucketCount{hm.currentBucketCount}, sz{hm.sz}
{
    arrayCopy(hm.Buckets_Array, Buckets_Array, currentBucketCount);

}


HashMap::~HashMap()
{
    for(int i = 0; i < currentBucketCount; i++)
    {
        deleteLinkedList(Buckets_Array[i]);
    }

    delete[] Buckets_Array;
}


HashMap& HashMap::operator=(const HashMap& hm)
{

    if (this != &hm)
    {

        Node** newNodeArray = new Node*[hm.currentBucketCount];

        fillArray(newNodeArray, hm.currentBucketCount);

        arrayCopy(hm.Buckets_Array, newNodeArray, currentBucketCount);
        currentBucketCount = hm.currentBucketCount;
        sz = hm.sz;

        for (int i = 0; i < currentBucketCount; i++)
        {
            deleteLinkedList(Buckets_Array[i]);
        }

        delete[] Buckets_Array;
        Buckets_Array = newNodeArray;

    }

    return *this;
} 

void HashMap::add(const std::string& key, const std::string& value)
{
    // REHASH IF EXCEEDED LOAD FACTOR
    double futureLoadFactor = double((sz + 1))/double(currentBucketCount);

    if (futureLoadFactor > maximumLoadFactor)
    {
        rehashKeys();
    }

    unsigned int index = getIndex(key);

    if (!checkExists(Buckets_Array[index], key, value))
    {

        if (Buckets_Array[index] == nullptr)
        {
            Node* n = new Node;
            n->key = key;
            n->value = value;
            n->next = nullptr;
            Buckets_Array[index] = n;
        }

        else
        {

            addToEnd(Buckets_Array[index], key, value);

        }

        sz += 1;
    }


}

以下是我使用的一些帮助成员函数:

void HashMap::fillArray(Node** nodeArray, int size)
{
    for (int i = 0; i < size; i++)
    {
        nodeArray[i] = nullptr;
    }
}

void HashMap::rehashKeys()
{
    currentBucketCount = (currentBucketCount  * 2) + 1;
    Node** tempBucketsArry = new Node* [currentBucketCount];
    fillArray(tempBucketsArry, currentBucketCount);

    std::cout << "MAX INDEX: " << currentBucketCount/2 << std::endl;
    for (int i = 0; i < currentBucketCount/2; i++)
    {
        hashLinkedList(Buckets_Array[i], tempBucketsArry);
        deleteLinkedList(Buckets_Array[i]);

    }
    delete[] Buckets_Array;
    Buckets_Array = tempBucketsArry;

}


 void HashMap::hashLinkedList(Node* node, Node**& node_arry)
 {
    if (node != nullptr)
    {
        int newIndex = getIndex(node->key);          
        addToEnd(node_arry[newIndex], node->key, node->value);
        hashLinkedList(node->next, node_arry);

    }
 }

void HashMap::copyNode(Node* sourceNode, Node* targetNode)
{


    targetNode->key = sourceNode->key;
    targetNode->value = sourceNode->value;
    sourceNode = sourceNode->next;

    while (sourceNode != nullptr)
    {
        Node* tempNode = new Node;
        tempNode->key = sourceNode->key;
        tempNode->value = sourceNode->value;
        targetNode->next = tempNode;
        targetNode = targetNode->next;
        sourceNode = sourceNode->next;

    }

    targetNode->next = nullptr;

}



void HashMap::arrayCopy(Node** source, Node**& target, int arrysz)
{

    for (int i = 0; i < arrysz; i++)
    {
        if (source[i] != nullptr)
        {

            Node* copy = new Node;
            copyNode(source[i], copy);
            target[i] = copy;
        }

        else
        {
            target[i] = nullptr;
        }
    }


}

void HashMap::deleteLinkedList(Node* node)
{




    while (node != nullptr)
    {
        if (node->next == nullptr)
        {
            delete node;
            break;

        }

        else
        {
            Node* next = node->next;
            delete node;
            node = next;
        }
    }

}

//  Adds node to the end of linked list

void HashMap::addToEnd(Node*& node, std::string key, std::string value)
{

    if ( node == nullptr )
    {
        Node* n = new Node;
        n->key = key;
        n->value = value;
        n->next = nullptr;
        node = n;

    }


    else
    {

        addToEnd(node->next, key, value);

    }

}

当我运行memcheck时,它说错误在deleteLinkedList函数中,在这一行:

if (node->next == nullptr)

由于问题仅在重新发生时发生,我更倾向于检查rehashing函数,但是如果我不调用赋值运算符重载方法,则rehashing函数可以正常工作。我真的很感激任何帮助。

谢谢。

1 个答案:

答案 0 :(得分:0)

this->currentBucketCount中,您在致电hm.currentBucketCount之前忘记将arrayCopycurrentBucketCount分配。

您应该交换这两个语句并保留deleteLinkedList的旧值来调用 arrayCopy(hm.Buckets_Array, newNodeArray, currentBucketCount); currentBucketCount = hm.currentBucketCount;

    int oldBucketCount = currentBucketCount;
    currentBucketCount = hm.currentBucketCount;
    arrayCopy(hm.Buckets_Array, newNodeArray, currentBucketCount);
    ...
    for (int i = 0; i < oldBucketCount; i++)
    {
        deleteLinkedList(Buckets_Array[i]);
    }

替换为

    arrayCopy(hm.Buckets_Array, newNodeArray, hm.currentBucketCount);
    // currentBucketCount = hm.currentBucketCount;
    // sh = hm.sz;
    for (int i = 0; i < currentBucketCount; i++)
    {
        deleteLinkedList(Buckets_Array[i]);
    }
    currentBucketCount = hm.currentBucketCount;
    sh = hm.sz;

<tbody>
<tr>
    <?php
        while($getdata = mysqli_fetch_array($result))
        {
            echo"<td>".$getdata['x_id']."</td>";
            echo"<td>".$getdata['x_title']."</td>";
            echo"<td>".$getdata['x_track']."</td>";
            echo"<td>".$getdata['x_tag']."</td>";
            echo"<td>".$getdata['x_model']."</td>";
            echo'<td><img class="img-table-thumbnail" src="'.$getdata['x_thumb'].'"></td>';
            echo'<td><a type="button" class="btn btn-sm btn-default" href="'.$getdata['x_link'].' " target="_BLANK">VISIT</a></td>'; 
            echo'<td><form action="delete.php" method="post" enctype="multipart/form-data">
            <button type="submit" name="deleteData" class="btn-sm btn-primary" value=".$getdata['x_id']."><i class="fa fa-times-circle" aria-hidden="true"></i></button>
            </form></td>';
            echo "</tr>";
        }

        //$result = mysqli_query($db_connect,$sql);

        $db_connect->Close();
    ?>