C++ 哈希表问题

Posted

技术标签:

【中文标题】C++ 哈希表问题【英文标题】:C++ Hashtable Problem 【发布时间】:2011-04-19 10:37:14 【问题描述】:

嗨,我试图在 c++ 中使用 Hastable 来存储字符串,即字符串键和数据。我使用的是 2003 年出版的《游戏程序员的数据结构》一书中的代码。

虽然我实现了一个 int hastable,但当我尝试对字符串 one 执行相同操作时,我却陷入了错误。

c++ 一直给我同样的错误;

//code
#include <string>
#include <iostream>
#include "HashTable.h"

using namespace std;


//hash table
//***********************************************************************
unsigned long int Hash( int i )

    return i;


unsigned long int StringHash( const char* p_string )

    unsigned long int hash = 0;
    int i;
    int length = strlen( p_string );
    for( i = 0; i < length; i++ )
    
        hash += ( (i + 1) * p_string[i] );
    
    return hash;


HashTable<string, string> table( 10, StringHash ); <<--problem here ERROR BELOW
HashEntry<string, string>* entry;
//***********************************************************************

错误 6 错误 C2664: 'HashTable::HashTable(int,无符号 long (__cdecl *)(KeyType))' : 不能 将参数 2 从 'unsigned 长 (__cdecl *)(const char *)' 到 '无符号长(__cdecl *)(KeyType)' j:\my_docs\college 2010 -2011\游戏数据结构\ca3_datastructures_gerry mc donnell\ca3_datastructures_gerry mc donnell\loginuser.h 31 CA3_DataStructures_gerry 麦克唐纳

如果有人能提供帮助,那就太好了。

本书给出了字符串哈希函数,所以我不确定我做错了什么。

哈希表.h

// ============================================================================
// Data Structures For Game Programmers
// Ron Penton
// HashTable.h
// This file holds the Linekd Hash Table implementation.
// ============================================================================


#ifndef HASHTABLE_H
#define HASHTABLE_H

#include "DLinkedList.h"
#include "Array.h"


// -------------------------------------------------------
// Name:        HashEntry
// Description: This is the hash table entry class. It
//              stores a key and data pair.
// -------------------------------------------------------
template< class KeyType, class DataType >
class HashEntry

public:
    KeyType m_key;
    DataType m_data;
;



// -------------------------------------------------------
// Name:        HashTable
// Description: This is the hashtable class.
// -------------------------------------------------------
template< class KeyType, class DataType >
class HashTable

public:

    // typedef the entry class to make is easier to work with.
    typedef HashEntry<KeyType, DataType> Entry;


// ----------------------------------------------------------------
//  Name:           HashTable
//  Description:    construct the table with a size, and a hash 
//                  function. The constructor will construct the 
//                  m_table array with the correct size.
//  Arguments:      p_size: The size of the table
//                  p_hash: the hashing function.
//  Return Value:   None
// ----------------------------------------------------------------
    HashTable( int p_size, unsigned long int (*p_hash)(KeyType) )
        : m_table( p_size )
    
        // set the size, hash function, and count.
        m_size = p_size;
        m_hash = p_hash;
        m_count = 0;
    


// ----------------------------------------------------------------
//  Name:           Insert
//  Description:    Inserts a new key/data pair into the table. 
//  Arguments:      p_key: the key
//                  p_data: the data attached to the key.
//  Return Value:   None
// ----------------------------------------------------------------
    void Insert( KeyType p_key, DataType p_data )
    
        // create an entry structure.
        Entry entry;
        entry.m_data = p_data;
        entry.m_key = p_key;

        // get the hash value from the key, and modulo it
        // so that it fits within the table.
        int index = m_hash( p_key ) % m_size;

        // add the entry to the correct index, increment the count.
        m_table[index].Append( entry );
        m_count++;
    


// ----------------------------------------------------------------
//  Name:           Find
//  Description:    Finds a key in the table
//  Arguments:      p_key: the key to search for
//  Return Value:   a pointer to the entry that has the key/data,
//                  or 0 if not found.
// ----------------------------------------------------------------
    Entry* Find( KeyType p_key )
    
        // find out which index the key should exist in
        int index = m_hash( p_key ) % m_size;

        // get an iterator for the list in that index.
        DListIterator<Entry> itr = m_table[index].GetIterator();

        // search each item
        while( itr.Valid() )
        
            // if the keys match, then return a pointer to the entry
            if( itr.Item().m_key == p_key )
                return &(itr.Item());
            itr.Forth();
        

        // no match was found, return 0.
        return 0;
    


// ----------------------------------------------------------------
//  Name:           Remove
//  Description:    Removes an entry based on key 
//  Arguments:      p_key: the key
//  Return Value:   true if removed, false if not found.
// ----------------------------------------------------------------
    bool Remove( KeyType p_key )
    
        // find the index that the key should be in.
        int index = m_hash( p_key ) % m_size;

        // get an iterator for the list in that index.
        DListIterator<Entry> itr = m_table[index].GetIterator();

        // search each item
        while( itr.Valid() )
        
            // if the keys match, then remove the node, and return true.
            if( itr.Item().m_key == p_key )
            
                m_table[index].Remove( itr );
                m_count--;
                return true;
            
            itr.Forth();
        

        // item wasn't found, return false.
        return false;
    


// ----------------------------------------------------------------
//  Name:           Count
//  Description:    Gets the number of entries in the table.
//  Arguments:      None
//  Return Value:   Number of entries in the table.
// ----------------------------------------------------------------
    int Count()
    
        return m_count;
    


// ----------------------------------------------------------------
//  Name:           m_size
//  Description:    This is the size of the table
// ----------------------------------------------------------------
    int m_size;

// ----------------------------------------------------------------
//  Name:           m_count
//  Description:    This is the number of entries in the table.
// ----------------------------------------------------------------
    int m_count;

// ----------------------------------------------------------------
//  Name:           m_table
//  Description:    This is the actual table, a list of linked 
//                  lists of entries.
// ----------------------------------------------------------------
    Array< DLinkedList< Entry > > m_table;

// ----------------------------------------------------------------
//  Name:           m_hash
//  Description:    a pointer to the hash function.
// ----------------------------------------------------------------
    unsigned long int (*m_hash)(KeyType);


;


#endif

//数组.h

【问题讨论】:

不应该StringHashstring 作为参数而不是const char* 只是出于好奇;本书建议在示例中使用什么编译器? 【参考方案1】:

您的Hashtable 构造函数需要散列函数接受KeyType 参数。

您正在创建一个Hashtable,其中std::stringKeyType,但传递了一个带有char* 参数的哈希函数。这些不兼容。

要么使用char* 键类型进行散列,要么将散列函数更改为使用std::string

【讨论】:

【参考方案2】:

HashTable.h 中,哈希函数具有函数签名unsigned long int (*p_hash)(KeyType)。也就是说,如果您的哈希表是HashTable&lt;string, string&gt;,则哈希函数的预期形式是unsigned long int (*p_hash)(string),而不是发布的unsigned long int (*p_hash)(const char*)

【讨论】:

【参考方案3】:
HashTable<string, string> table( 10, StringHash );

string(第二个模板参数)是您的 KeyType,但您的哈希函数需要 const char *

要么

unsigned long int StringHash( const string & p_string )

 HashTable<string, const char *> table( 10, StringHash );

应该可以。 (尚未编译或测试)

【讨论】:

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

在 C++ 中删除哈希表

C++ 哈希表查询_进入哈希函数结界的世界

C++进阶第二十一篇——哈希(概念+哈希函数+哈希冲突+哈希表+哈希桶+代码实现)

C++ 哈希表问题

c++,在哈希表中显示内容的方法。使用双链表

哈希表的性能,为啥C++最慢?