哈希表的重载[]运算符到向量

时间:2012-09-28 11:36:15

标签: c++ oop vector operator-overloading hashtable

我正在使用C ++中的简单哈希表。我有方法插入,删除和搜索指定键的哈希表。我知道C ++ map STL容器可以处理我的情况,但我想把自己编写为一个教育练习。

基本上我有一个哈希表,它将采用一个字符串并将其映射到其他字符串的向量。这在方法中很容易实现,因为调用.Add()或.Delete()将按预期运行。但是,我想为能够对向量执行这些操作的类创建一个重载的[]运算符。

例如,如果我想在向量中添加一个项目,我可以这样写:

     hashTable[string1] = newString;

这会将新字符串设置为vector的成员。删除和搜索也是如此。

    hashTable[string1] = "";
    cout << hashTable[string1] << endl;

我的主要问题是我不知道如何重载[]运算符以获得此功能。我现在编写了这个功能。它适用于基本的1到1字符串匹配,但不适用于字符串到矢量匹配。

    //Return a reference to a vector to update then reassign?

        vector& HashClass::operator[](const string index)
        {
           assert(size >= 0 && size < maxSize); 
           Hash(key);
           return hashTable[index];     
        }

我认为我最常想的是有一个向后返回的想法,以后需要分配。作为用户,我会发现这个kludgy。

2 个答案:

答案 0 :(得分:0)

在C ++中,[]对关联容器的访问通常被赋予默认的语义 - 构造映射类型的对象,使用键插入它,并返回对插入的映射对象的引用。

因此,您的operator[]将实现为:

    string& HashClass::operator[](const string index)
    {
       assert(size >= 0 && size < maxSize); 
       Hash(key);
       vector &v = hashTable[index];     
       if (index in v) {
          ...
       } else {
          v.push_back(string());
          return v.back();
       }
    }

答案 1 :(得分:0)

这个问题与另一个问题密切相关:行为是什么 当你访问一个非存在的值而不是一个时,你想要的 分配?换句话说,当你写作时你想要发生什么:

std::cout << hashTable[string] << std::endl;
表中没有

string

有两种可能的方法:你可以认为它是一个错误,并且 抛出异常,或中止或类似的东西;或者你可以回来 某种默认值,使用默认构造函数构建,或由提供者提供 客户早些时候。

标准地图和unordered_map采用第二种方法,使用 用于构造新值的默认构造函数。这允许非常简单 解决方案:如果operator[]不存在,则插入它,初始化它 使用默认值。然后你返回一个引用; hashTable[string] = newString;通过引用来指定 已存在的价值。

在许多使用案例中,第一种方法更可取(也许是一种 contains功能,因此您可以预先测试是否operator[] 会找到或不会找到的东西)。要实现第一种方法,您必须 首先为每种访问类型实现特定的功能:

template <typename Key, typename Value>
class HashTable
{
public:
    Value* get( Key const& key ) const;
    void set( Key const& key, Value const& value );
};

(我通常将这些公开;没有理由禁止他们使用 客户。)

然后,您定义operator[]以返回代理,如下所示:

template <typename Key, typename Value>
class HashTable
{
public:
    class Proxy
    {
        HashTable* myOwner;
        Key myKey;
    public:
        Proxy( HashTable* owner, Key const& key )
            : myOwner( owner )
            , myKey( key )
        {
        }

        operator Value const&() const
        {
            Value const* result = myOwner->get( myKey );
            if ( result == NULL ) {
                //  Desired error behavior here...
            }
            return *result;
        }

        Proxy const& operator==( Value const& value ) const
        {
            myOwner->set( myKey, value );
            return *this;
        }
    };

    Value* get( Key const& key ) const;
    void set( Key const& key, Value const& value );

    Proxy operator[]( Key const& key )
    {
        return Proxy( this, key );
    }
};

因此,当你写:

hashTable[key] = newString;

,代理operator=将调用hashTable.put( key, newString ); 但是,在其他上下文中,它将调用隐式类型转换 代理,调用hashTable.get( key )

在某些情况下,即使您希望返回默认值,也可能是 最好使用此解决方案:不需要get函数 在哈希表中插入任何内容,因此表格不会填满 所有未命中,你可以重载operator[] const,所以 您也可以在const哈希表上使用它。而且,它没有 要求值类型具有默认构造函数。

对于使用的解决方案,它确实有一个缺点 标准;由于您无法重载operator.,因此无法创建代理 表现得像一个参考,像:

hashTable[string].someFunction();

不行。解决方法是在代理中重载operator->,但是 这会导致一种不自然的语法:

hashTable[string]->someFunction();  //  But the hash table contains
                                    //  values, not pointers!!!

(不要因隐式转换为引用而误导 表达式中a不会考虑隐式转换 a.b。)