哈希表和链表的 C++ 访问冲突

Posted

技术标签:

【中文标题】哈希表和链表的 C++ 访问冲突【英文标题】:C++ Access Violation With Hash Tables and Linked Lists 【发布时间】:2013-03-10 01:28:18 【问题描述】:

所以我一直在尝试创建一个处理 1000 个链表的类,并最初声明指向它们的指针。

这是直接处理我的问题的代码:

struct node

    char name[40];
    char numb[12];
    node * next;
;
class hashTable

public:
    //Creates a table of 1000 pointers to linked-list nodes
    node * table[1000];

//Functions
void addNode(char name[40], char numb[12])

    node * temp;        //Initializes temp node as pointer
    temp = new node;    //Points temp node to a new node

    int hash = h(g(name));  //The hash of the key (name) used to check nodes
    temp = table[hash];     //sets the temporary node to the first node of the list

    while (temp->next != 0)
    
//...

就在 while 循环中,我收到错误“访问冲突读取位置 0xcccccd00” 我不确定为什么它无法访问表成员,除非可能是因为这些值尚未初始化或其他原因?

【问题讨论】:

可能是因为这些值没有被初始化或者什么的? 我会说这是未初始化内存的偏移量。由于 0xcccccccc 表示在 VC 调试模式下未初始化。 ***.com/questions/127386/… 站点注释:将表格大小更改为 997 或 1009。 您是否将表 [] 中的所有 1000 个指针都设为 NULL?好像你没有,因为你没有检查。等待一分钟不应该 temp = table[hash];成为表[hash]=temp; 你能在上面发布的代码中包含你的类构造函数吗?然后,将table 添加到初始值设定项列表中,特别是hashTable::hashTable() : table()。另外,检查您刚刚从表之前收到的temp,以使用temp->next 取消引用它。据您所知,之前没有任何东西,而且它不是一个有效的地址。 【参考方案1】:

您可能不会做两件事。首先确保您的哈希表已正确初始化为包含全空指针。其次,确保从哈希表中检索到的任何指针在解除引用之前是有效的

第一期:

hashTable::hashTable() : table()


另外,你要确保这东西正确清理

hashTable::~hashTable()

    for (size_t i=0;i<sizeof(table)/sizeof(table[0]); ++i)
    
        node *temp = table[i];
        while (temp)
        
            node *victim = temp;
            temp = temp->next;
            delete victim;
        
    

第二期:

void addNode(const char *name, const char *numb)

    int hash = h(g(name));    //The hash of the key (name) used to check nodes
    node *temp = table[hash]; //sets the temporary node to the first node of the list

    if (temp)
    
        // preexisting entry. walk that list looking for matching key.
        node **pp = &temp->next;
        while (temp)
        
            if (0 == strcmp(temp->name, name))
                break;
            pp = &temp->next;
            temp = temp->next;
        

        // link to last node if not found in list
        if (!temp)
            *pp = new node(name, numb);
    
    else
       // no prior entry. create a new one and store it at table[hash].
        table[hash] = new node(name, numb);
    

注意:以上代码假设节点类实现为

struct node

    char name[40];
    char numb[12];
    node * next;

    node(const char* name_, const char *numb_)
        : next()
    
        strncpy(name, name_, sizeof(name)/sizeof(name[0])-1);
        name[ sizeof(name)/sizeof(name[0])-1 ] = 0;
        strncpy(numb, numb_, sizeof(numb)/sizeof(numb[0])-1);
        numb[ sizeof(numb)/sizeof(numb[0])-1 ] = 0;
    
;

就个人而言,我会使用std::string

【讨论】:

这似乎比我的猜测更有可能。结果 temp = new node;在这种情况下没有任何意义。 非常感谢您的详细解答。现在开始有意义了。 :) 呃,最后一件事。使用代码初始化指向 NULL 的指针,当我多次使用相同的确切条目时,此“if (temp)”现在永远不会为假。 @KevSana 第一次时间槽被映射并且冲突列表存在时将是错误的。之后,添加的每个插槽中的初始节点始终是该插槽集合列表的第一个节点。这就是冲突列表的起点。顺便说一句,如果你也对集合列表进行排序,你可以显着加快速度,但这会改变你的哈希表的布局,需要一个数组指针和每个槽的列表大小。如果速度是最终目标,那么值得考虑。【参考方案2】:

如果 hash 的值大于(或等于)1000,temp 将指向一个无效区域。

而且您正在泄漏由new node 分配的内存,因为您正在覆盖临时变量。

【讨论】:

以上是关于哈希表和链表的 C++ 访问冲突的主要内容,如果未能解决你的问题,请参考以下文章

字典与哈希表(HashMap)

C中线性表和链表的区别

数据结构之顺序表和链表的区别

顺序表和链表的详细对比

LinkedHashMapt深入学习

数据结构与算法之数组链表和哈希表的Java实现