哈希映射直接访问运算符[]
hash map direct access operator []
我实现了一个哈希表(std::unordered_map
):
#include <bits/stdc++.h>
#ifndef HASH_TABLE_H
#define HASH_TABLE_H
#define TABLE_SIZE 100
// Hash node class template
template <typename K, typename V>
class HashNode {
public:
HashNode(const K &key, const V &value)
: key(key)
, value(value)
, next(NULL) {
}
K getKey() const {
return key;
}
V getValue() const {
return value;
}
void setValue(V value) {
HashNode::value = value;
}
HashNode *getNext() const {
return next;
}
void setNext(HashNode *next) {
HashNode::next = next;
}
private:
// key-value pair
K key;
V value;
// next bucket with the same key
HashNode *next;
};
// Default hash function class
template <typename K>
struct KeyHash {
unsigned long operator()(const K& key) const {
return reinterpret_cast<unsigned long>(key) % TABLE_SIZE;
}
};
// Hash map class template
template <typename K, typename V, typename F = KeyHash<K>>
class HashTable {
public:
HashTable() {
// construct zero initialized hash table of size
table = new HashNode<K, V> *[TABLE_SIZE]();
}
~HashTable() {
// destroy all buckets one by one
for (int i = 0; i < TABLE_SIZE; ++i) {
HashNode<K, V> *entry = table[i];
while (entry != NULL) {
HashNode<K, V> *prev = entry;
entry = entry->getNext();
delete prev;
}
table[i] = NULL;
}
// destroy the hash table
delete [] table;
}
bool get(const K &key, V &value) {
unsigned long hashValue = hashFunc(key);
HashNode<K, V> *entry = table[hashValue];
while (entry != NULL) {
if (entry->getKey() == key) {
value = entry->getValue();
return true;
}
entry = entry->getNext();
}
return false;
}
void put(const K &key, const V &value) {
unsigned long hashValue = hashFunc(key);
HashNode<K, V> *prev = nullptr;
HashNode<K, V> *entry = table[hashValue];
while (entry != nullptr and entry->getKey() != key) {
prev = entry;
entry = entry->getNext();
}
if (entry == nullptr) {
entry = new HashNode<K, V>(key, value);
if (prev == nullptr) {
// insert as first bucket
table[hashValue] = entry;
} else {
prev->setNext(entry);
}
} else {
// just update the value
entry->setValue(value);
}
}
// direct access operator overloading
V& operator [] (const K& key) {
V value;
get(key, value);
return value;
}
void remove(const K &key) {
unsigned long hashValue = hashFunc(key);
HashNode<K, V> *prev = nullptr;
HashNode<K, V> *entry = table[hashValue];
while (entry != nullptr and entry->getKey() != key) {
prev = entry;
entry = entry->getNext();
}
if (entry != nullptr) {
if (prev == nullptr) {
// remove first bucket of the list
table[hashValue] = entry->getNext();
} else {
prev->setNext(entry->getNext());
}
delete entry;
}
}
private:
// hash table
HashNode<K, V> **table;
F hashFunc;
};
#endif // HASH_TABLE_H
struct MyKeyHash {
unsigned long operator()(const int& k) const {
return k % 10;
}
};
int main(void) {
HashTable<int, std::string, MyKeyHash> hmap;
hmap.put(1, "val1");
hmap.put(2, "val2");
hmap.put(3, "val3");
std::string value;
// hmap.get(2, value);
std::cout << hmap[2] << std::endl; // val2
// hmap[2] = "val_new";
// std::cout << hmap[2] << std::endl; // val2
bool res = hmap.get(3, value);
if (res)
std::cout << value << std::endl; // val3
hmap.remove(3);
res = hmap.get(3, value);
if (res)
std::cout << value << std::endl; // nothing
return 0;
}
问题是直接访问运算符[]
重载无法正常工作。我可以通过hmap[1]
访问密钥,因为函数签名是V& operator [] (const K& key)
,但我不能像hmap[1] = "something"
那样赋值,因为它不返回任何将覆盖值的指针。如何实现这两种功能?
更改:
V& operator [] (const K& key) {
V value;
get(key, value);
return value;
}
进入:
V& operator [] (const K& key) {
unsigned long hashValue = hashFunc(key);
HashNode<K, V> *entry = table[hashValue];
while (entry != NULL) {
if (entry->getKey() == key) {
return entry->getValue();
}
entry = entry->getNext();
}
// alternatively, as suggested by NetVipeC, you can return
// here a reference to default-constructed element under given key
// e.g.: put(key, V{}); return (*this)[key];
throw std::range_error{"Key not found!"};
}
并使HashNode::getValue
也返回参考:
V& getValue() {
return value;
}
const V& getValue() const {
return value;
}
相关文章:
- 运行时多态性 - 箭头运算符访问了错误的成员?
- 如果键不存在,使用 [] 运算符访问 STL Map 元素会添加新元素
- 通过 [] 运算符访问unordered_map时出错
- 为什么我不能使用 [] 运算符访问 nlohmann C++ JSON 库中的数组?
- 如何使用运算符 [] 访问结构的指定字段值
- 为什么在递增后使用 [] 运算符访问指针数组会返回错误地址的当前内存位置
- 如何使用字符串字符数组中的 ++ 运算符访问下一个字符串
- 将对象数限制为1可以使用点运算符访问静态成员的1
- 提升:使用运算符 [] 访问 bimap
- 为什么默认情况下使用 [ ] 运算符访问超出范围的矢量元素时,C++检测?
- 如何使用 offset 运算符访问字符串的字符,并且字符串位于字符串向量中
- 如何在 vim 中将访问时的向量转换为运算符 [ ] 访问
- 在C++中,我可以使用箭头运算符访问另一个运算符吗
- 无法使用运算符 [] 访问二维堆向量的元素
- 在指向 wstring 的指针上使用 [ ] 运算符访问元素
- 使用作用域运算符访问非静态成员变量
- 使用运算符[]访问一个函数中的字符串会影响C++中另一个函数的输出
- 何时使用 " . " 或 " -> " 运算符访问属性或成员函数?
- 通过运算符 [] 访问静态成员unordered_map
- 试图使用运算符[]访问std::map元素时编译器错误