我需要对某些数据结构做出设计决策,以便快速访问。这里的场景: 我必须同步两个不同增长率的变量。我已按以下格式列出数据:
范围(Ai1,Ai2)〜范围(Bi1,Bi2)也就是说范围Ai1-Ai2与某些i匹配Bi1-Bi2
现在给定A的整个范围内的任何Ax,我应该能够确定(Bj1,Bj2)中的适当范围,反之亦然。数据类型明智:A是int; B是浮动的。
我不知道这个翻译最合适的数据类型是什么?我的主要要求是速度。此外,有关如何在C#中实现此数据结构的任何帮助都会有所帮助。
确保问题适合记忆。 A的跨度可以是0-300,000的范围,并且范围Ai1-Ai2的大小可以是10到300的范围;浮点的跨度范围是0到10,000.000(我们只使用3个小数位),范围Bi1 - Bi2的大小可以是0.100 - 10.000
另一个已知的事实是确保A是连续的而B可能不是。但两者同时增加,但速度不同。也不是Ranges重叠。两者都是单调增加的。
因此可以预期这样的事情:
(Ai1,Ai2)〜(Bi1,Bi2)
(1,78)〜(13.454,19.546)
(79,114)〜(19.712,22.335)
(115,198)〜(22.678,24.101)
查询:A = 99,预期响应:B范围=(19.712,22.335)
查询:B = 16.117,预期响应:范围=(1,78)
如果B不在前进范围内,则预期会进行舍入。
日Thnx-埃贡
答案 0 :(得分:1)
您的数据的关键属性是A
和关联的B
,范围:
这意味着简单的二进制搜索应该有效,并为您提供O(log(n))
查找。
按升序存储区间对的数组。
要执行查找(例如,在A
上),请在“密钥”间隔的start
属性上运行二进制搜索(在本例中为A
)以查找最高间隔,其开始小于要搜索的项目。然后检查该间隔是否包含项目(end >= toSearch
)。 “值”(在这种情况下,关联的B
间隔)提取是微不足道的 - 它是同一个数组元素的一部分。
反向查询(即从B
到A
)的工作方式大致相同。
答案 1 :(得分:1)
考虑这种一般方法:
定义ARange
和BRange
;并将它们指向对方:
class ARange
{
public int Low;
public int High;
public BRange B;
}
class BRange
{
public float Low;
public float High;
public ARange A;
}
通过互连两个实例的工厂方法构造ARange
和BRange
类对。
ARange
和BRange
存储在两个已排序的数组中。a
或b
值,请使用二进制搜索分别查找封面ARange
或BRange
,并检索相互关联的相对范围。在最坏的情况下,二进制搜索会给你O(log N)
查找复杂度,其中N分别是ARange
和BRange
数组的长度。这种特殊的弱类型Array.BinarySearch
重载可以给你一个kickstart。
如果您需要具有良好可读性的通用解决方案,则可以为(int, ARange)
和(float, BRange)
对重叠比较操作。
实施此算法后,请考虑以下优化:
ARange
和BRange
定义为struct
以减少动态分配的内存量,改善数据的位置并减少开销; ARange
s形成连续序列(即没有间隙),优化High
,并保持Low
,B
对和上限界定序列(比如,作为阵列中的人造元素); ARange
s / BRange
s进行比较; 增加数据位置(从而减少CPU缓存未命中)的另一个选项是将类分解为单个字段的数组,因此在二进制搜索中,您只需使用Low
限制,并仅对特定项目访问High
和A
/ B
:
int[] ALow; // Lows of A-ranges
int[] AHigh; // Highs of A-ranges
int[] AB; // index into B-arrays from A-ranges
float[] BLow; // Lows of B-ranges
float[] BHigh; // Highs of B-ranges
int[] BA; // index into A-arrays from B-ranges