搜索第一个免费索引

时间:2013-06-12 18:04:29

标签: c algorithm data-structures

我有一个100万ID的大数组/列表,然后我需要找到可以使用的第一个免费ID。可以假设有几个模块引用该数据结构并取一个id(在此期间它应标记为已使用),然后稍后返回(应标记为空闲)。 我想知道可以使用哪些不同的数据结构?我可以用什么算法有效地实现时间和空间(单独)。 请原谅,如果它已经存在,我在发布前进行了搜索。

6 个答案:

答案 0 :(得分:7)

可能有效的一个初步想法是存储所有未使用ID的优先级队列,并对其进行排序,以便在高ID之前将低ID出列。使用标准二进制堆,这可以在O(log n)时间内将ID返回到未使用的ID池,并在O(log n)时间内查找下一个空闲ID。这样做的缺点是它需要您显式存储所有ID,如果存在大量ID,这可能是空间效率低的。

一种潜在的节省空间的优化方法是尝试将连续的ID值合并到ID范围中。例如,如果您有免费ID 1,3,4,5,6,8,9,10和12,则可以存储范围1,3-6,8-10和12.这将需要您稍微改变底层数据结构。您可以使用存储范围的平衡二叉搜索树,而不是使用二进制堆。由于这些范围不会重叠,因此您可以将范围比较为小于,等于或大于其他范围。由于BST以排序顺序存储,您可以通过获取树的最小元素(在O(log n)时间内)并查看其范围的低端来找到第一个空闲ID。然后,您将更新范围以排除第一个元素,这可能需要您从树中删除空范围。将ID返回到未使用的ID池时,您可以执行前导和后继搜索,以确定ID之前和之后的范围。如果其中任何一个都可以扩展为包含该ID,则可以扩展范围。 (您可能还需要合并两个范围)。这也只需要O(log n)时间。

希望这有帮助!

答案 1 :(得分:6)

一种天真但有效的方法是将所有ID存储在堆栈中。 获取id是一个恒定时间操作:弹出列表的第一项。 当任务结束时,只需将ID推入堆栈。

如果必须返回最低的空闲ID(而不是任何空闲ID),则可以使用带插入的最小堆,并在O(log N)中弹出最低值。

答案 2 :(得分:2)

尝试使用链表(id的链表)。链接所有那些列表,头部应该指向空闲列表(假设在init都是免费的)。每当它被标记为已使用时,将其删除并将其放在列表的末尾,并使头指向下一个空闲列表。这样,您的列表将以“从免费使用”的方式构建。您还可以在O(1)中获得免费列表。此外,当一个id被标记为空闲时 - 将它作为链表的第一个成员(因为它变得空闲,它变得可用),即指向此列表。希望这会有所帮助!

答案 3 :(得分:0)

序言:二进制堆确实是最好的答案。我将在这里提出一个替代方案,在某些情况下可能会有优势。

一种可能的方法是使用Fenwick Tree。您可以在每个位置存储0或1,表示已经使用过某个位置。你可以通过二分搜索找到第一个空位(找到总和为n-1的第一个范围[1..n])。这个操作的复杂性是O(log ^ 2 n),这比二进制堆更糟糕,但这种方法还有另一个优点:

  • 您可以在少于10行代码中实现Fenwick树
  • 您现在可以计算O(log n)
  • 范围内的密度(使用次数/总ID)

答案 4 :(得分:0)

如果您不是严格需要最低ID,则可以将批量分配给1000个模块。当释放ID时,可以将它们添加到列表的后面。有时您会对列表进行排序,以确保再次指定您分配的ID来自低端。

答案 5 :(得分:-1)

嗯,数组可能不是最好的结构。哈希会更好,至少速度快。至于每个“节点”的结构,我能看到你需要的只是id,无论是否使用它。