【发布时间】:2017-08-30 20:48:11
【问题描述】:
我试图了解我应该如何实现一个关联数组,它为搜索操作提供恒定的时间,现在我的实现看起来像这样:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
template <class Key, class Value> class Dict {
private:
typedef struct Item {
Value value;
Key key;
} Item;
vector<Item> _data;
public:
void clear() {
_data.clear();
}
long size() {
return _data.size();
}
bool is_item(Key key) {
for (int i = 0; i < size(); i++) {
if (_data[i].key == key) return true;
}
return false;
}
bool add_item(Key key, Value value) {
if (is_item(key)) return false;
Item new_item;
new_item.key = key;
new_item.value = value;
_data.push_back(new_item);
return true;
}
Value &operator[](Key key) {
for (int i = 0; i < size(); i++) {
if (_data[i].key == key) return _data[i].value;
}
long idx = size();
Item new_item;
new_item.key = key;
_data.push_back(new_item);
return _data[idx].value;
}
Key get_key(long index) {
if (index < 0) index = 0;
for (int i = 0; i < size(); i++)
if (i == index) return _data[i].key;
return NULL;
}
Value &operator[](long index) {
if (index < 0) index = 0;
for (int i = 0; i < size(); i++) {
if (i == index) return _data[i].value;
}
return _data[0].value;
}
};
一个简单的测试:
class Foo {
public:
Foo(int value) {
_value = value;
}
int get_value() {
return _value;
}
void set_value(int value) {
_value = value;
}
private:
int _value;
};
template <class Key, class Value> void print_dict(Dict<Key, Value> &dct) {
if (!dct.size()) {
printf("Empty Dict");
}
for (int i = 0; i < dct.size(); i++) {
printf("%d%s", dct[dct.get_key(i)], i == dct.size() - 1 ? "" : ", ");
}
printf("\n");
}
int main(int argc, char *argv[]) {
printf("\nDict tests\n------------\n");
Dict<string, int> dct;
string key1("key1");
string key2("key2");
string key3("key3");
dct["key1"] = 100;
dct["key2"] = 200;
dct["key3"] = 300;
printf("%d %d %d\n", dct["key1"], dct["key2"], dct["key3"]);
printf("%d %d %d\n", dct[key1], dct[key2], dct[key3]);
print_dict(dct);
dct.clear();
print_dict(dct);
Dict<Foo *, int> dct2;
Foo *f1 = new Foo(100);
Foo *f2 = new Foo(200);
dct2[f1] = 101;
dct2[f2] = 202;
print_dict(dct2);
}
事情是这样的,现在搜索操作是线性时间,我希望它变成常数时间,我想知道一种简单/轻量级的方法来实现这一点。
我已经看到hashtables 是一种可能的选择,但我不希望不必为每个对象实现哈希函数。也许类似于unordered_map...不知道。
谁能提供一些想法,或者提供一个简单的轻量级实现来实现我在这里尝试实现的目标?
在这个虚构的示例中,我使用 std::vector 来避免使问题变得更大更复杂,但我真正的用例根本不会使用 STL(即:我将编写我自己的 std::vector 自定义实现)
约束
- 根本不使用 STL 的原因不是因为该实现不够好(快速、通用、全功能),而是因为对于我的规模受限的项目来说相当繁重 (final exe <=65536bytes)。即使是 STL 的这个小实现,实际上也相当大,可以按原样使用
- 我不需要关联数组的完整实现,只需提供我在上面已经实现的接口(主要问题是线性时间搜索)
- 我不在乎插入/删除方法很慢,但我绝对希望搜索/查找接近恒定时间
- 我想我需要使用哈希表将上述实现转换为关联数组,但我不确定相关的实现细节(每个对象的哈希函数、表大小...)
【问题讨论】:
-
std::unordered_map 有什么问题?你这样做是为了编程挑战吗?或许可以解释一下为什么你需要这个新容器。
-
@BPL 没有描述性并不是 _T0 和 _T1 的唯一问题。它们是保留标识符,因此程序将具有未定义的行为。
-
@BPL 仅仅因为某一时刻在一台机器上的一次测试给出了预期的输出,并不意味着程序是正确的,或者在不同的情况下输出是正确的。如果你的程序违反了标准,它就如履薄冰。您的新标识符仍然保留。欲了解更多信息:en.cppreference.com/w/cpp/language/identifiers
-
@BPL "以下划线后跟大写字母的标识符被保留;"
-
渐近地我很确定保证
O(1)访问时间的唯一方法是拥有一个非冲突哈希函数。 (或者,至少对碰撞有一些硬性限制)
标签: c++ associative-array