问题
从下面的项目列表中,我将需要通过标识具有给定值的键范围来访问该项目,例如,假设值是否为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
?
答案 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", °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
的二进制搜索-总秒数值,对于您的计算机而言,该秒数可能比较快,也可能不快。
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树数据结构代替哈希映射。