我有一个JavaScript程序,我将在其中管理很多整数范围。在这种情况下,范围只是一个开始和结束值(或任何等价的,如开始和长度值),并引用另一个对象。范围可以重叠,并且可以相同(尽管引用的对象将不同)。
可能的起始值和结束值介于0和4294967295之间(2 32 - 1或0xFFFFFFFF
),尽管域中有几个大的“漏洞”,任何范围都不会覆盖,甚至部分。与可能性领域相比,大多数范围将非常小:我预计绝大多数范围的长度将小于2000.
此结构的最重要用例是查找包含给定整数值的所有范围。大多数情况下,我希望查找失败(没有包含给定值的范围)。
否则,我显然还需要向它添加元素(通常)并从中删除元素(很少)。有一段时间,我也需要找到与给定范围重叠的所有范围,而不是包含单个值的所有范围。
我可以使用哪种数据结构?范围列表中的线性搜索是不切实际的,因为查找在大多数情况下都会失败;而且我需要经常进行查找。
答案 0 :(得分:1)
二叉树,其中键是起始(低)值。找到钥匙后,你可以很容易地看到它(更高和更低)。
答案 1 :(得分:0)
我喜欢System.Tuple这样的东西[或F#列表,但很少有人知道F#]。
如果范围是连续的,那么将起始和结束整数作为元组元组nums =(开始,结束)变得简单,否则将具有起始端的元组作为元组的第一个条目和列表因为第二个可能适合你,Tuple nums =((开始,结束),List)。
答案 2 :(得分:0)
如果将所有范围的开头和结尾存储在一个列表中作为映射回到范围索引,则可以按顺序n执行。即mylist = [{45:range1},{47:range2},{55:range1},{57:range2}] 您可以扫描列表并在第一次看到标记时设置布尔值为true,第二次看到标记时设置为false。当你发现一个高于你的数字时,你可以知道你在哪个范围内。您可以使用bisect插入O(logn),而删除和插入是O(n)。祝好运! 〜奔
答案 3 :(得分:0)
ATTEMPT 1:
保留2个二叉树,一个用于起始值,另一个用于结束值。让两个树的节点(或者只是'end')具有一个属性,该属性通过某个id(范围的起始值)引用唯一范围。
在“开始”树上执行二进制搜索,将列表缩小到开始小于或等于搜索值的范围。在“结束”树上执行相同操作,其中值大于或等于搜索值。查找两个树中节点的交集,这些范围包含您的搜索值。
您可以使用哈希映射/集合找到交叉点以获得最佳性能。
ATTEMPT 2:
如果您保留一个哈希列表,其中的键是第一个,那么起始值和结束值共享的位数是多少?
因此,如果start为'11001101'且end为'11010010',则键为'110'。每个键都将映射到共享密钥的范围列表(开始和结束)。
当搜索值以查看它们所在的范围时,例如'00101111',您必须在哈希列表中搜索n个不同的值,或者这样,其中n是位数(在您的情况下为32) )。在这种情况下,您将搜索“00101111”,“0010111”,“001011”等。对于每次点击,您必须实际检查搜索值是否在范围内。
乍一看,在我看来,平均而言,对于你得到的每一次击打,一半都是误报,但是如果击中的数量很小则无关紧要,键越大则命中越少它应该得到。有一个小问题,例如'00101110'的开头和'01100111'的结尾,因为键是'0'意味着会有大量的'误报'。更好的是,如果有2个不同的键,'001'和'01',虽然我不确定您需要为此优化编码的特定算法。如果范围足够小并且可以解决或忽略此问题,那么您可以获得非常快速的查找,因为大多数密钥相对较长且与搜索不匹配。