我需要多次访问二叉树的最小元素。有哪些实现方式可以在 常数时间 内访问最小元素,而不是 O(log n)
?
我需要多次访问二叉树的最小元素。有哪些实现方式可以在 常数时间 内访问最小元素,而不是 O(log n)
?
这可能听起来有些愚蠢,但如果您主要访问最小元素,并且不太改变树的结构,那么在添加/删除时(在任何树上),维护指向最小元素的指针可能是最佳解决方案。
/usr/src/linux/kernel/sched_fair.c
中的cfs_rq.rb_leftmost
。 - ephemient遍历树的时间复杂度始终为O(log n)。你是自己编写树实现的吗?你可以在你的数据结构旁边简单地隐藏当前最低值元素的引用,并在添加/删除节点时更新它。(如果你没有编写树,则也可以通过将树实现包装在自己的包装对象中来完成相同的操作。)
Comparator
的TreeSet
将项目按正确顺序排序以存储单个元素,然后只需调用SortedSet#first()
或#last()
以尽可能高效地获取最大/最小值。TreeSet
插入新项略慢,但如果您没有大量不断变化的元素,则不应该成为问题。O(log n)
。 - Rudiger如果您可以使用一些内存,那么组合集合可能适合您。
例如,您要查找的内容听起来很像链表。您始终可以访问最小元素,但是插入或查找任意节点可能需要更长的时间,因为您必须进行O(n)的查找。
如果您将链表和树结合起来,可能会得到两全其美的效果。为了查找项目以进行获取/插入/删除操作,您将使用树来查找元素。元素的“持有者”节点必须具有从树到链表的跨越方式,以进行删除操作。此外,链表必须是双向链表。
因此,我认为获取最小项将是O(1),任何任意查找/删除将是O(logN)--我认为即使插入也将是O(logN),因为您可以在树中找到放置它的位置,查看前一个元素并从那里穿过到您的链表节点,然后添加“下一个”。
嗯,这开始看起来像是一个非常有用的数据结构,可能会浪费一些内存,但我认为除非您必须重新平衡树,否则任何操作都不会比O(logN)更糟糕。
如果您将二叉树升级/“upcomplex”为线索二叉树,则可以获得O(1)的第一个和最后一个元素。
您基本上需要保留对当前第一个和最后一个节点的引用。
在插入后立即检查,如果第一个节点的前一个非空,则更新第一个节点。最后一个节点同理。
每当您删除时,首先检查要删除的节点是否是第一个或最后一个。然后相应地更新存储的第一个和最后一个节点。