我做了以下涉及二元堆结构的算法:
Algorithm: heapMinimum(node)
Input : Position n
Output : Sequence minList; containing the postions that hold the minimum value
1. minList <-- sequence
2. if parent(node) == NULL // current node is the root of the tree
3. minList.insertLast(node)
4. if (leftchild(node).element() == node.element())
5. concat(heapMinimum(leftchild(node), minList))
6. if(right(node).element() == node.element())
7. concat(heapMinimum(rightChild(node), minList))
8. return minList
算法的作用基本上是遍历二进制堆,给定其根,以查找并存储保持最小值的节点(即与根的值匹配的值)。
现在我无法用Big O表示法计算算法的运行时间。我感到困惑的原因是因为用于遍历每个节点的左右子节点的递归。
除O(1)
外,所有操作都在concat
的固定时间内运行。但是,如何计算这种递归解决方案的运行时间呢?
答案 0 :(得分:4)
对我来说看起来像O(N),其中N是元素的数量。如果您的堆只包含相同的元素,则将遍历所有元素。另外,为什么不是concat O(1)?只要你“连接”数字,它也应该是O(1)。如果以某种方式concat是O(N)(从你的伪代码看起来它是 - 但你应该重新考虑,如果你真的需要连接两个返回的列表),那么总时间将是O(N 2 )最坏的情况。
答案 1 :(得分:1)
我假设你在谈论二进制堆?
通过定义堆属性,您应该只进行递归,直到找到大于根的元素为止。但是,您还必须确保树的当前级别的其他元素都不与根相同。从本质上讲,这会产生这样的规则:一旦遇到堆的元素大于根,您就不需要递归到元素的子元素中。
但是,在最坏的情况下,每个元素可能等于根。在这种情况下,您必须检查整个堆,这会产生O(n)时间,其中n是堆中元素的数量。
所以回答你的问题,是O(n)
答案 2 :(得分:0)
正如其他人所提到的,如果你的concat()是O(1)[如果不是,你就可以这样做]那么你的算法就是输出大小的O(N)。
但是,如果您使用了复制列表的concat()(取决于系统,这很容易意外),那么最坏的情况是输出大小为O(N ^ 2)。导致此行为的一种情况是,当您的最小节点深入到树中时,您的concat()会不断复制每个级别的列表。
请注意,此深度受堆深度的限制,因此如果树是平衡的,则最坏的情况也是数据结构大小为O(M log M)。您可以看到这一点,因为最大副本数是树的深度。
答案 3 :(得分:0)
我想您的解决方案中存在错误。 第一次检查:
必须删除如果parent(node)== NULL
,但必须添加 node!= NULL 的检查。
此外,我建议使用list作为附加参数,您将在其中提供答案。 那么,这就是我的实施:
Algorithm: heapMinimum(node, minList)
if (node != NULL)
{
if (minList.empty() || minList.getFirst().element() == node.element())
{
minList.insertLast(node)
heapMinimum(left(node), minList)
heapMinimum(right(node), minList)
}
}
假设在列表中添加一个元素取O(1),我们得到该函数需要O(k),其中k是堆中最小值的数量。
享受。