Javascript 我可以使用什么数据结构来存储和检索离散值的范围?

Javascript 我可以使用什么数据结构来存储和检索离散值的范围?,javascript,data-structures,Javascript,Data Structures,我有一个JavaScript程序,我将在其中管理许多整数范围。在此上下文中,范围只是一个起始值和一个结束值(或任何等效值,如起始值和长度值),并引用另一个对象。范围可以重叠,也可以相同(尽管引用的对象将不同) 可能的起始值和结束值介于0和4294967295之间(232-1或0xffffff),尽管域中有几个大的“洞”,任何范围都无法覆盖,甚至部分覆盖。与可能性范围相比,大多数范围将非常小:我预计绝大多数范围的长度将小于2000 这个结构最重要的用例是查找包含给定整数值的所有范围。大多数情况下,

我有一个JavaScript程序,我将在其中管理许多整数范围。在此上下文中,范围只是一个起始值和一个结束值(或任何等效值,如起始值和长度值),并引用另一个对象。范围可以重叠,也可以相同(尽管引用的对象将不同)

可能的起始值和结束值介于0和4294967295之间(232-1或
0xffffff
),尽管域中有几个大的“洞”,任何范围都无法覆盖,甚至部分覆盖。与可能性范围相比,大多数范围将非常小:我预计绝大多数范围的长度将小于2000

这个结构最重要的用例是查找包含给定整数值的所有范围。大多数情况下,我希望查找失败(没有包含给定值的范围)

否则,我显然还需要向其中添加元素(经常),并从中删除元素(很少)。偶尔,我也需要找到与给定范围重叠的所有范围,而不是包含单个值的所有范围


我可以使用什么样的数据结构?在范围列表中进行线性搜索是不切实际的,因为查找大部分时间都失败;而且我需要非常经常地进行查找。

我喜欢这种东西的System.Tuple[或F列表,但很少有人知道F]


如果范围是连续的,这使得将开始和结束整数作为元组tuple nums=(开始,结束)变得简单,否则将具有开始-结束的元组作为元组的第一个条目,将列表作为第二个条目可能对您有用,tuple nums=((开始,结束),列表).

如果将所有范围的开始和结束存储在一个列表中,作为返回范围索引的映射,则可以按顺序n进行。ie mylist=[{45:range1},{47:range2},{55:range1},{57:range2}]
然后,您可以扫描列表,并在第一次看到标记时将布尔值设置为true,在第二次看到标记时将布尔值设置为false。当你发现一个数字高于你的数字时,你就可以知道你在哪个范围内。您可以使用对分来插入O(logn),而删除和插入是O(n)。祝你好运~Ben

二叉树,其中键是起始(低)值。一旦你找到一把钥匙,你就可以很容易地看得更宽(更高和更低)。

尝试1:

保留两个二叉树,一个用于起始值,一个用于结束值。让两个树的节点(或仅“结束”)都有一个属性,该属性通过某个id(范围的起始值)引用唯一的范围

在“开始”树上执行二进制搜索,将列表缩小到开始小于或等于搜索值的范围。在值大于或等于搜索值的“结束”树上执行相同操作。从两棵树中查找节点的交点,这些范围包含您的搜索值

您可以使用哈希映射/集合来找到交叉点,以获得最佳性能

尝试2:

如果您保留了一个哈希列表,其中键是起始值和结束值共享的第一个位,那么会怎么样

因此,如果开始为“11001101”,结束为“11010010”,则键为“110”。每个键将映射到共享该键的范围列表(开始和结束)

当搜索一个值以查看它们所处的范围时,例如“00101111”,您必须在哈希列表中搜索n个不同的值,其中n是位数(在您的示例中为32)。在本例中,您将搜索“00101111”、“0010111”、“001011”等。对于每次点击,您必须实际检查搜索值是否在范围内

乍一看,在我看来,平均而言,每点击一次,就会有一半是误报,但如果点击次数少,这并不重要,而且按键越大,点击次数就越少


例如,“00101110”的开头和“01100111”的结尾有一个小问题,因为键是“0”,这意味着将有大量的“误报”。如果有两个不同的键,“001”和“01”会更好,尽管我不确定您需要为这个优化编码的特定算法。如果范围足够小,并且这个问题可以解决或忽略,那么您可以获得非常快速的查找,因为大多数键相对较长,并且与搜索不匹配。

范围是否以0和max_int为界?或者-inf到inf?什么是范围?它只是一个
[min,max]
对吗?@kojiro,是的,
[start,end]
[start,length]
都可以。你在什么环境下编程?对于稀疏数组的属性没有确定的顺序的旧JS实现,这是否适用?有多少范围?它的数量是数千、数百万,还是应该有任何数字(即,甚至数十亿)?存储在Javascript中也非常简单,因为创建数组的语法非常简洁:
var nums=[start,end]
。不过,正如你从那篇评论中猜到的那样,这不是我关心的问题。我正在寻找一种方法,根据范围集合中是否包含值来查找范围,并且对我管理的所有范围进行线性搜索不会剪切它。此外,我使用的是Javascript,因此.NET类不是解决方案。线性时间太昂贵,因为我有很多范围,而且我查找的值通常不存在,这是线性搜索的最坏情况。或者是每个节点都有16个子节点的树。它非常适合于值的范围。使用带有start键的二叉树可以帮助我找到需要测试的最后一个范围,因为任何
start
低于我要查找的值的范围都有可能有足够的
end
来匹配。在一般情况下,这将减少hal