在哈希表范围内查找键的最佳算法
Best algorithm to find a key within a range from hashtable
问题
从下面的项目列表中,我需要通过识别具有给定值的键范围来访问该项目,例如假设值是 2.1.1,以度、分和秒为单位,我需要找到键 0.0。 0-30.0.0
性能是高优先级。
key: 0.0.0-30.0.0 value: x-y-z
key: 30.0.0-60.0.0 value: y-x-z
key: 60.0.0-90.0.0 value: z-y-z
方案一:
以下是我目前尝试过的解决方案
重新创建新的 key/value (json) 文件如下
key: 0.0.0 value: x-y-z
key: 0.0.1 value: x-y-z
.
key: 0.0.59 value: x-y-z
.
key: 0.1.0 value x-y-z
key: 0.1.1 value x-y-z
key: 30.0.0 value: y-x-z
.
.
key: 30.0.59 value: y-x-z
.
key: 30.1.0 value: y-x-z
key: 30.1.1 value: y-x-z
key: 30.1.2 value: y-x-z
.
.
key: 30.1.59 value: y-x-z
key: 30.2.0 value: y-x-z
key: 30.2.1 value: y-x-z
key: 30-2.3 value: y-x-z
.
.
key: 60.0.0 value: z-y-x
key: 60.0.1 value: z-y-x
key: 60.0.2 value: z-y-x
.
.
key: 60.0.59 value: z-y-x
key: 60.1.0 value: z-y-x
key: 60.1.1 value: z-y-x
.
.
问题
上述解决方案的问题是文件大小会增加,这会导致我的紧凑型应用程序出现堆溢出
解决方案2
?
散列 table 不太适合解决此问题,因为当您可能查找的所有键都存储在 table 中时,散列 table 的效果最好:您已经说你没有那个记忆。二进制搜索确实是一个很好的方法,但是你提到...
The key range is in sorted array binary search maybe expensive as these are not direct numbers hence parsing converting from DMS to decimal and then performing comparison could have a performance issue, this function to be triggered every second.
首先,C++ 程序可以在一秒钟内完成 很多 的工作——即使是未优化的查找也可能足够快地工作,但让我们假设您确实需要更接近最佳速度的那一刻...
"parsing from DMS" 是模糊的,但我假设你的意思是你有一个键的文本表示,例如“2.1.1”进入你的程序:解析它几乎肯定比必须解析它更好使用文本比较进行查找。要解析 "C++ style" 中的文本,您只需使用...
std::istringstream iss(the_incoming_key);
int degree, minute, second;
char c1, c2;
if (iss >> degree >> c1 >> minute >> c2 >> seconds &&
c1 == '.' && c2 == '.')
{
// have parsed a valid key...
}
else
error_throw_exit_whatever();
如果您准备使用较旧的 C 函数来提高速度,请考虑:
if (sscanf(the_incoming_key.c_str(), "%d.%d.%d", °ree, &minute, &second) == 3)
// have parsed a valid key...
解析密钥后,您可以合理地:
1) 有 std::map<tuple<int8_t, int8_t, int8_t>, Value> values;
和二进制搜索 std::make_tuple(degree, minute, second)
,或
2) 具有 std::map<int, Value> values;
和二进制搜索 degree * 3600 + minute * 60 + second
- 总秒数 值对您的计算机来说可能会或可能不会更快比较。
虽然乘法有点慢,但可以使用 (degree << 12) + (minute << 6) + second
来避免它,因为六位足以存储 0 到 59 之间的值。
当然,在解析 json 文件和填充 table.
时,无论您为创建密钥所做的任何转换都需要在之前使用过
为了进一步优化,您可以拥有一个 360 度地图数组,并在您想要查找分钟和秒组件的特定地图中建立索引。将搜索 space 除以 360 可以预期在每次地图查找时消除 8 或 9 次比较(因为每次比较都会将仍在竞争的元素数量减半,而 360 介于 2^8 和 2^9 之间) .
由于您在第一个 json 中的条目已按顺序排序,您可以解析您的输入并使用它来计算位置并生成条目的键。
对于第一个列表,我会将输入值解析为 3 个整数。对于这个,我们只需要输入的第一部分(学位)。
然后我们得到这样的位置:
int position = input_degree / step_size;
step_size 在您的第一个列表中将是 30。
如果您需要密钥,您现在可以使用以下位置生成它:
String key_begin = position * step_size;
String search_key = key_begin + ".0.0-" + key_begin+step_size + ".0.0";
使用 KD 树或 R 树数据结构而不是哈希映射。
问题
从下面的项目列表中,我需要通过识别具有给定值的键范围来访问该项目,例如假设值是 2.1.1,以度、分和秒为单位,我需要找到键 0.0。 0-30.0.0 性能是高优先级。
key: 0.0.0-30.0.0 value: x-y-z
key: 30.0.0-60.0.0 value: y-x-z
key: 60.0.0-90.0.0 value: z-y-z
方案一: 以下是我目前尝试过的解决方案
重新创建新的 key/value (json) 文件如下
key: 0.0.0 value: x-y-z
key: 0.0.1 value: x-y-z
.
key: 0.0.59 value: x-y-z
.
key: 0.1.0 value x-y-z
key: 0.1.1 value x-y-z
key: 30.0.0 value: y-x-z
.
.
key: 30.0.59 value: y-x-z
.
key: 30.1.0 value: y-x-z
key: 30.1.1 value: y-x-z
key: 30.1.2 value: y-x-z
.
.
key: 30.1.59 value: y-x-z
key: 30.2.0 value: y-x-z
key: 30.2.1 value: y-x-z
key: 30-2.3 value: y-x-z
.
.
key: 60.0.0 value: z-y-x
key: 60.0.1 value: z-y-x
key: 60.0.2 value: z-y-x
.
.
key: 60.0.59 value: z-y-x
key: 60.1.0 value: z-y-x
key: 60.1.1 value: z-y-x
.
.
问题 上述解决方案的问题是文件大小会增加,这会导致我的紧凑型应用程序出现堆溢出
解决方案2
?
散列 table 不太适合解决此问题,因为当您可能查找的所有键都存储在 table 中时,散列 table 的效果最好:您已经说你没有那个记忆。二进制搜索确实是一个很好的方法,但是你提到...
The key range is in sorted array binary search maybe expensive as these are not direct numbers hence parsing converting from DMS to decimal and then performing comparison could have a performance issue, this function to be triggered every second.
首先,C++ 程序可以在一秒钟内完成 很多 的工作——即使是未优化的查找也可能足够快地工作,但让我们假设您确实需要更接近最佳速度的那一刻...
"parsing from DMS" 是模糊的,但我假设你的意思是你有一个键的文本表示,例如“2.1.1”进入你的程序:解析它几乎肯定比必须解析它更好使用文本比较进行查找。要解析 "C++ style" 中的文本,您只需使用...
std::istringstream iss(the_incoming_key);
int degree, minute, second;
char c1, c2;
if (iss >> degree >> c1 >> minute >> c2 >> seconds &&
c1 == '.' && c2 == '.')
{
// have parsed a valid key...
}
else
error_throw_exit_whatever();
如果您准备使用较旧的 C 函数来提高速度,请考虑:
if (sscanf(the_incoming_key.c_str(), "%d.%d.%d", °ree, &minute, &second) == 3)
// have parsed a valid key...
解析密钥后,您可以合理地:
1) 有 std::map<tuple<int8_t, int8_t, int8_t>, Value> values;
和二进制搜索 std::make_tuple(degree, minute, second)
,或
2) 具有 std::map<int, Value> values;
和二进制搜索 degree * 3600 + minute * 60 + second
- 总秒数 值对您的计算机来说可能会或可能不会更快比较。
虽然乘法有点慢,但可以使用 (degree << 12) + (minute << 6) + second
来避免它,因为六位足以存储 0 到 59 之间的值。
当然,在解析 json 文件和填充 table.
时,无论您为创建密钥所做的任何转换都需要在之前使用过为了进一步优化,您可以拥有一个 360 度地图数组,并在您想要查找分钟和秒组件的特定地图中建立索引。将搜索 space 除以 360 可以预期在每次地图查找时消除 8 或 9 次比较(因为每次比较都会将仍在竞争的元素数量减半,而 360 介于 2^8 和 2^9 之间) .
由于您在第一个 json 中的条目已按顺序排序,您可以解析您的输入并使用它来计算位置并生成条目的键。
对于第一个列表,我会将输入值解析为 3 个整数。对于这个,我们只需要输入的第一部分(学位)。 然后我们得到这样的位置:
int position = input_degree / step_size;
step_size 在您的第一个列表中将是 30。
如果您需要密钥,您现在可以使用以下位置生成它:
String key_begin = position * step_size;
String search_key = key_begin + ".0.0-" + key_begin+step_size + ".0.0";
使用 KD 树或 R 树数据结构而不是哈希映射。