【问题标题】:two way ranged lookup table, C#双向范围查找表,C#
【发布时间】:2011-03-09 16:14:43
【问题描述】:

我需要对某些数据结构做出设计决定,以便快速访问。这里的场景: 我必须同步两个不同增长率的变量。我已按以下格式列出数据:

Range(Ai1,Ai2)~Range(Bi1,Bi2)也就是说范围Ai1-Ai2匹配Bi1-Bi2对于一些i

现在给定 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 可能不是。但两者都同时增加,但速度不同。范围也没有重叠。两者都是单调递增的。

所以可以期待这样的事情:

(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,预期响应:A 范围 = (1,78)

如果 B 不在范围内,则需要向前舍入。

Thnx-Egon

【问题讨论】:

  • 我假设我们的问题适合记忆?但我完全不明白你的问题,你想和谁做什么?你能详细说明一下吗?
  • 现在根据要求提供详细说明。
  • 任何范围都可以重叠吗?
  • 范围不重叠,单调递增。
  • 我能想到的最直接的方法是 O(log n) 对 A 范围进行二进制搜索以找到正确的范围,然后返回相应的 B 范围,反之亦然跨度>

标签: c# performance data-structures


【解决方案1】:

考虑这种通用方法:

  1. 定义ARangeBRange;并将它们相互指向:

    class ARange
    {
        public int Low;
        public int High;
        public BRange B;
    }
    
    class BRange
    {
        public float Low;
        public float High;
        public ARange A;
    }
    
  2. 通过互连两个实例的工厂方法构造一对 ARangeBRange 类。

  3. ARanges 和BRanges 存储在两个排序数组中。
  4. 具有特定的ab 值,使用二分查找分别查找覆盖ARangeBRange,并检索相互关联的相反范围。

在最坏的情况下,二分搜索会给你一个 O(log N) 查找复杂度,其中 N 分别是 ARangeBRange 数组的长度。这种特殊的弱类型 Array.BinarySearch 重载可以让您快速启动。

如果您需要具有良好可读性的通用解决方案,您可以重载 (int, ARange)(float, BRange) 对的比较操作。

实现此算法后,考虑以下优化:

  • ARangeBRange定义为structs,以减少动态分配的内存量,提高数据的局部性,并减少开销;
  • 提供ARanges 形成一个连续序列(即没有间隙),优化High,并保留成对的LowB 和一个界定序列的上限(例如,作为数组);
  • 提供自定义二进制搜索实现,允许您将整数/浮点数与ARanges/BRanges 进行比较;
  • 增加数据局部性(从而减少 CPU 缓存未命中)的另一个选项是将类分解为单个字段的数组,因此在二进制搜索中,您可以只使用 Low 边界,并访问 @ 987654349@ 和 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
    

【讨论】:

    【解决方案2】:

    您的数据的关键属性是对于A 和关联的B,范围:

    1. 不要重叠。
    2. 单调增加。

    这些意味着简单的二分搜索应该可以有效地工作,并为您提供O(log(n)) 查找。

    按升序存储区间对数组。

    要执行查找(例如,A),请对“关键”区间(在本例中为 A)的 start 属性运行二进制搜索以找到 最高 开始小于要搜索的项目的间隔。然后检查该区间是否包含项目 (end >= toSearch)。 “值”(在本例中为关联的 B 区间)很容易提取 - 它是同一数组元素的一部分。

    反向查找(即从BA)的工作方式几乎相同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-11
      • 2013-10-17
      • 2015-07-26
      • 2013-03-04
      相关资源
      最近更新 更多