双向远程查找表,C#

时间:2011-03-09 16:14:43

标签: c# performance data-structures

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

范围(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-埃贡

2 个答案:

答案 0 :(得分:1)

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

  1. 不要重叠。
  2. 单调增加。
  3. 这意味着简单的二进制搜索应该有效,并为您提供O(log(n))查找。

    按升序存储区间对的数组。

    要执行查找(例如,在A上),请在“密钥”间隔的start属性上运行二进制搜索(在本例中为A)以查找最高间隔,其开始小于要搜索的项目。然后检查该间隔是否包含项目(end >= toSearch)。 “值”(在这种情况下,关联的B间隔)提取是微不足道的 - 它是同一个数组元素的一部分。

    反向查询(即从BA)的工作方式大致相同。

答案 1 :(得分: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. ARangeBRange存储在两个已排序的数组中。
  4. 拥有特定的ab值,请使用二进制搜索分别查找封面ARangeBRange,并检索相互关联的相对范围。
  5. 在最坏的情况下,二进制搜索会给你O(log N)查找复杂度,其中N分别是ARangeBRange数组的长度。这种特殊的弱类型Array.BinarySearch重载可以给你一个kickstart。

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

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

    • ARangeBRange定义为struct以减少动态分配的内存量,改善数据的位置并减少开销;
    • 提供ARange s形成连续序列(即没有间隙),优化High,并保持LowB对和上限界定序列(比如,作为阵列中的人造元素);
    • 提供自定义二进制搜索实现,允许您将整数/浮点数与ARange s / BRange s进行比较;
    • 增加数据位置(从而减少CPU缓存未命中)的另一个选项是将类分解为单个字段的数组,因此在二进制搜索中,您只需使用Low限制,并仅对特定项目访问HighA / 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