查找表如何精确工作以及如何实现它们?

时间:2018-08-01 03:27:36

标签: c++ dictionary if-statement hashtable lookup

我最近制作了一个程序,该程序处理许多if / else语句以返回特定值。有人建议改为使用查找表。我的问题是,

  1. 它们如何工作以及如何实施?
  2. 地图,哈希表和查找表之间有什么区别。

这一切都将使用C ++,而且我是C ++初学者。

2 个答案:

答案 0 :(得分:1)

您的问题确实很广泛,因为StackOverflow并非教程站点,但今天早上我感到很高兴...

“查找表”只是一个容器(任何一种容器),其中包含您要查找的值,并且通常映射到其他某个值。

以最简单的形式,考虑以下几点:

struct MapIntToString
{
    int value;
    char* string;
};

MapIntToString my_map[] = {
    { 1, "one" },
    { 2, "two" },
    { 3, "three" },
    // ...
};

以上内容可以视为查找表。您可以在my_map上进行迭代(循环)以查找(查找)整数2,然后从中选取字符串"two"

根据您的需求和用例,上面的示例可能还不够。上面的代码基本上是在普通C而不是C ++中通常完成的方式。对于C ++,有更好的容器来映射值,例如std::mapstd::unordered_map

然而,有时标准类型可能不够用,还有许多其他数据结构可用于查找内容。

答案 1 :(得分:1)

  

我的问题是,它们如何工作以及如何实施?什么是   stl映射,哈希表和查找表之间的区别。

您要寻找的是一种有效的机制,通过该机制您可以查找与给定键对应的值。

您当前的机制(一长串的if / else-if命令)效率很低,因为如果您有N种可能的值可供选择,则您(平均)必须将候选密钥与(N / 2)在找到匹配的其他键之前,您可以停止查找。 (这称为O(N)复杂度)

那还有其他选择吗?

最简单的一个实际上就是一个值数组,例如

const char myLookupTable[1000] = {
    "zero",
    "one",
    "two",
    [...]
    "nine hundred and ninety-nine"
};

...使用类似的查找表,您将得到一个键(在这种情况下,该键是介于0和999之间的数字,包括0和999之间的数字),并通过单个数组查找来查找相应的值:

 const char * val = myLookupTable[500];

这是超高效的(O(1)复杂度–始终在恒定的时间内完成,而不管数组有多大!),但仅在键为连续(且相对)为无符号整数的情况下才有效小)的值范围。例如,如果您的键是字符串,则此方法将不适用。

为获得更大的灵活性,下一个选项是STL的std::mapstd::map为您提供从任何键类型到任何值类型的快速键->值查找。在内部,它以tree的形式实现:每个键值对都以这种方式插入树中:树保持排序,树的最小键在树的左边,而最大的键在树的右边。因此,在std::map中查找键(及其关联的值)只是从树的根节点开始,然后将该节点处的键与要查找的键进行比较即可:比你的钥匙?然后移到右边的孩子。还是比您的钥匙大?然后移到左手孩子。重复该过程,直到到达树的底部,这时您将找到所要查找的键值对,或者发现它不存在。这是一种O(log(N))复杂度的算法,因为对于其中具有N个值的树,需要log(N)比较才能完成查找。 O(log(N))被认为是相当不错的效率。

您提到的最终数据结构是hash table(如std::unordered_map所示)。哈希表的处理方式略有不同-在内部它是一个数组,但是为了避免查找表方法的局限性,它还附带一种算法,用于确定给定键/值对在其数组中的位置要存储。它通过为传入的键对象计算<哈希>哈希代码,然后使用该代码计算数组的偏移量(例如int array_offset = hash_code % array_size)并查看该插槽来实现此目的在数组中查看所请求的键值对是否存在。如果是,那么就完成了(再次执行O(1)性能!);或者如果插槽为空,那么它将知道您的密钥不在表中,并且可以立即返回失败(再次为O(1))。如果该插槽被其他一些键/值对占用,则哈希表将需要使用其他算法来整理hash collision;不同的哈希表以不同的方式处理,但通常仍然相当有效。