查找表到底是如何工作的以及如何实现它们? [关闭]

2024-07-04

我最近编写了一个程序,该程序处理大量 if/else 语句以返回特定值。有人建议改用查找表。我的问题是,

  1. 它们是如何工作的以及您如何实施它们?
  2. 映射、哈希表和查找表之间有什么区别。

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

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

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

那么还有哪些其他选择呢?

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

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

...使用这样的查找表,您可以获取一个键(在本例中是 0 到 999 之间的数字,包括 0 和 999),并使用单个数组查找来查找相应的值:

 const char* val = myLookupTable[myKeyIndex];

这是超级高效的(O(1) 复杂度——无论数组有多大,它总是在恒定时间内完成!),但它只适用于键是连续(且相对较小)范围内的无符号整数的情况的价值观。例如,如果您的键是字符串,则此方法不适用。

为了获得更大的灵活性,下一个选择是 STLstd::map. std::map为您提供从任何键类型到任何值类型的快速键->值查找。在内部它被实现为tree https://en.wikipedia.org/wiki/Red%E2%80%93black_tree:每个键值对都以这样的方式插入树中,使得树保持排序,最小的键位于树的左侧,最大的键位于右侧。因此,在 a 中查找键(及其关联值)std::map只需从树的根节点开始并将该节点的键与您正在查找的键进行比较:它是否小于您的键?然后转到右边的孩子。或者它比你的钥匙大?然后移动到左边的孩子。重复此操作,直到到达树的底部,此时您要么找到要查找的键值对,要么发现它不存在。这是一个复杂度为 O(log(N)) 的算法,因为对于其中有 N 个值的树,需要 log(N) 次比较才能完成查找。 O(log(N)) 被认为是相当不错的效率。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

查找表到底是如何工作的以及如何实现它们? [关闭] 的相关文章

  • 调用 std::adjacent_difference() 时的隐式转换

    我想获得相邻之间距离的向量points在向量中 struct Point double x y z vector
  • 函数 try 块什么时候有用?

    我想知道程序员何时使用函数 try 块 什么时候有用 void f int i try if i lt 0 throw less than zero std cout lt lt greater than zero lt lt std en
  • TortoiseGit / Winforms:合并时解析 Resource.resx

    我对 TortoiseGit 还很陌生 想知道如果 resx 文件发生冲突 如何在合并过程中解决它 例如 我可以从菜单中选择 使用他们的 尝试进行拉动和推动 但这是正确的方法吗 我可以以某种方式使用他们的并通过我的项目更改重建它吗 差异 以
  • 哪个STL容器具有线程安全的插入过程?

    哪个STL容器具有线程安全的插入过程 我希望多个线程同时插入同一个容器中 欢迎除 STL 即 Boost 之外的任何实现 STL 容器不是线程安全的 如果您愿意的话 您必须通过自己的同步来强加这一点
  • 如何在C#中隐藏文件?

    我想在c 中隐藏一个文件 我知道文件路径并且可以创建 FileInfo 对象 我怎样才能隐藏它 之前接受的答案 File SetAttributes path FileAttributes Hidden 将导致它可能丢失某些其他属性 因此您
  • 如何使用 MVVM light 处理 WP 8.1 上的后退按钮?

    我正在寻找适当的方法来处理 Windows Phone 8 1 WinRT 上的后退按钮按下事件NavigationService在 MVVM light 5 上可用 到目前为止 我认为最好的地方是在ViewModelLocator通过注册
  • Google 的“编码折线算法”的 C# 实现

    有谁有 Google 的简洁而强大的实现吗 编码折线算法 http code google com apis maps documentation utilities polylinealgorithm html in C 我本质上想要实现
  • 与对象的互斥体

    我试图了解如何在 C 中将互斥体与对象一起使用 我有以下 简单的 多线程代码用作速度测试 struct Rope int n steps offset std mutex mut Rope Rope int n int steps int
  • c malloc 问题(内存损坏)

    使用 malloc 时 如果它生成带有错误的核心转储 malloc memory corruption 这是否意味着 malloc 尝试分配无法自由分配的内存 如果是的话 造成这种情况的原因是什么 这完全取决于您的 malloc 实现 但通
  • 如何使文本框的自动完成列表可编辑?

    我有一个包含很多内容的应用程序TextBox使用自动完成的控件 每个人都使用AutoCompleteMode CustomSource从关联的获取自动完成文本AutoCompleteStringCollection 每当用户在其中输入新值时
  • 错误:扩展器控件可能无法在 PreRender 之前注册

    我正在尝试将 Ajax 控件添加到我的 aspx 页面 我刚刚添加了
  • 通过“this->member”访问c++成员类比隐式调用“member”更快/更慢

    经过我们的朋友谷歌搜索后 我无法得到以下观点的明确看法 我习惯这样称呼班级成员this gt 即使不需要 我发现它更明确 因为它在维护一些带有大量变量的繁重算法时很有帮助 当我正在研究一种应该优化的算法时 我想知道是否使用this gt 是
  • SQL 和 Dapper 性能隐式转换

    我们如何防止 Dapper 中的 SQL 隐式转换 我们意识到 我们正在进行 SQL 隐式转换 导致索引扫描和死锁 Dapper 参数是 nvarchar 而 SQL 表列是 varchar 这导致我们所有的 sql 列都转换为 nvarc
  • 使用Swashbuckle ISchemaFilter设置输入参数的默认描述

    我想在文档架构中为所有具有 DateTime 类型的输入参数添加默认描述 这样客户就会了解我们正在使用哪些格式等 我可以为此目的创建 ISchemaFilter 的自定义实现吗 我知道我可以使用 xml 注释添加描述 但在这种情况下 我应该
  • 如何通过可变参数模板表达概念?

    我想定义一个概念 只有具有特定类型值的元组才能满足 假设为了简单起见 我只想接受仅包含数字类型元素的元组 我该怎么做 e g std tuple
  • 如何使用 xstream 将 Hashmap 映射到 XML 中的键值属性

    我有以下实体 XStreamAlias entity public class MapTestEntity XStreamAsAttribute public Map
  • Blazor - 重定向到一个解决方案中另一个项目中的页面

    我遇到了这样的情况 在一个解决方案中 想要将用户从一个项目的页面重定向到另一个项目的页面 这很重要 我在 blazor 服务器上做 任何人都可以教我一些东西吗 您始终可以注入 NavigationManager 通过此您可以将用户重定向到另
  • 基于路由参数的子容器注册

    我们有一个多租户 ASP NET MVC 应用程序 为多个客户端托管预订引擎 这些客户端中的每一个都有多个可以影响 Unity 容器配置的包 我们为每个请求创建一个子容器 并根据通过路由传递的客户端和包参数注册不同的接口实现 目前 我们正在
  • Qt:如何处理用户按下“X”(关闭)按钮的事件?

    在 Qt 中 与用户单击窗口框架的 X 关闭 按钮 即此按钮 事件相对应的插槽是什么 如果没有这个插槽 在用户按下关闭按钮后是否有其他方法来触发功能 如果你有一个QMainWindow你可以覆盖closeEvent method inclu
  • 谷歌模拟 - 我可以在同一个模拟对象上多次调用 EXPECT_CALL 吗?

    如果我打电话EXPECT CALL在同一个模拟对象上两次TEST F 会发生什么 期望是否附加到模拟对象中 或者第二次调用是否消除了第一次调用的效果 I found 后子句 https github com google googletes

随机推荐