在哈希表范围内查找密钥的最佳算法

时间:2018-07-31 03:42:41

标签: json hashmap hashtable

问题

从下面的项目列表中,我将需要通过标识具有给定值的键范围来访问该项目,例如,假设值是否为2.1.1(以度,分钟和秒为单位),我需要找到键0.0.0- 30.0.0 性能是重中之重。

2018-07-30 23:36:24.980  INFO 197376 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration' of type [org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration$$EnhancerBySpringCGLIB$$e24a304] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-07-30 23:36:24.987  INFO 197376 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'stringOrNumberMigrationVersionConverter' of type [org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration$StringOrNumberToMigrationVersionConverter] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

解决方案1: 下面是我迄今为止尝试过的解决方案

按如下所示重新创建新的键/值(json)文件

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

问题 上述解决方案的问题是文件大小会增加,这会导致我的紧凑型应用程序中堆溢出

解决方案2

3 个答案:

答案 0 :(得分:8)

哈希表不太适合此问题,因为当您可能要查找的所有键都存储在表中时,哈希表最有效:您已经说过没有足够的内存。二进制搜索确实是实现此目的的一种好方法,但是您提到了...

  

键范围在排序数组二进制搜索中可能很昂贵,因为它们不是直接数字,因此解析从DMS转换为十进制然后执行比较可能会出现性能问题,该功能每秒都会触发。

首先,C ++程序可以在不到一秒钟的时间内完成很多的工作-即使未经优化的查找也可能足够快地工作,但让我们假设您做了一下需要接近最佳速度...

“从DMS解析”是模糊的,但是我假设您的意思是您要在程序中使用诸如“ 2.1.1”之类的键的文本表示形式:解析它肯定比必须执行使用文本比较进行查找。要以“ C ++样式”解析文本,只需使用...

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", &degree, &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的二进制搜索-总秒数值,对于您的计算机而言,该秒数可能比较快,也可能不快。

a。但是乘法有点慢,因此(degree << 12) + (minute << 6) + second可以避免这种情况,因为六位足以存储0到59之间的值。

当然,在解析json文件并填充表时,您需要使用任何用于创建密钥的转换。

为了获得更大的优化,您可以拥有360个地图的数组,并索引到要查找分钟和秒组成部分的特定地图。将搜索空间除以360预计将在您每次进行地图查找时消除8或9个比较(因为每个比较将仍在争用中的元素数量减半,而360在2 ^ 8和2 ^ 9之间)。

答案 1 :(得分:0)

由于您在第一个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";

答案 2 :(得分:0)

使用KD树或R树数据结构代替哈希映射。