- 你不在乎订购
- 您的密钥已经是随机的
- 1000 万件商品
简短的回答
哈希表可能最适合您的情况。
速度
如果散列是常数,则散列表 ( std::unordered_map
) 将为O ( 1 )。在您的情况下,O ( 1 ) 成立,因为您甚至不需要散列 - 仅使用随机 UUID 的低 32 位就足够了。查找的成本将类似于一两个指针间接。
二叉树 ( std::map
) 将为O ( log 2 n ),因此对于 1000 万个项目,您将有 24 次比较和 24 次潜在的缓存未命中。即使对于n = 4,000,它也会使用 12 次比较,因此它很快就会变得比哈希表差得多。
基数树将是O ( k ),因此您将有最多k个比较和k个潜在的缓存未命中。在极不可能的最好情况下,基数树将与哈希表一样快。更糟糕的是(假设k = 一个合理的 16,对于 256 路树)它会比二叉树执行得更好,但比哈希表差得多。
因此,如果速度是重中之重,请使用哈希表。
高架
一个典型的哈希表如果满了,每个项目将有大约 1-3 个开销指针。如果未满,您可能会在每个空槽中浪费 1 个空间指针。你应该能够保持它几乎满,同时仍然比二叉树更快,因为你有一个非常随机的密钥,但是为了尽可能快的速度,你当然希望给它足够的空间。对于 32 位机器上的 1000 万个项目,一个完整的表预计会有 38–114MiB 的开销。对于半满桌,预计 76–153MiB。
红黑树是最常见的std::map
实现,每个项目将有 3 个指针 + 1 个布尔值。一些实现利用指针对齐来将布尔值与其中一个指针合并。根据实现和哈希表的完整程度,红黑树的开销可能略低。预计 114–153MiB。
基数树每个项目有 1 个指针,每个空槽有 1 个指针。不幸的是,我认为如此大的随机键会导致您在树的边缘有很多空槽,因此它可能会比上述任何一个使用更多的内存。减小k可以降低这种开销,但同样会降低性能。
如果最小开销很重要,请使用哈希表或二叉树。如果是优先级,请使用完整的哈希表。
请注意,std::unordered_map
它不会让您控制何时调整大小,因此很难获得一个完整的。 Boost Intrusive有一个非常好的unordered_map
实现,可以让你直接控制它和许多其他事情。