有人可以描述一种算法,该算法在min-heap的数组实现中找到小于x的所有键。 我希望运行时间至少为O(k),其中k是报告的密钥数。
我现在一直在摸不着头脑。
答案 0 :(得分:4)
要获得“至少”的运行时间并不是那么困难,我认为你的意思是“最多”。
不幸的是,min-heap并不是很擅长找到除最小值之外的任何东西。
您可以对堆的树视图执行广度优先深度优先扫描,并终止到达X的每个分支。这将是O(k),但是很复杂
要查找Y< = X的所有Y,您也可以扫描整个数组,这将是O(n),但开销要少得多。
选择取决于比率n / k
答案 1 :(得分:4)
树最小堆有一个简单的递归算法:
void smaller_than(Node *node, int x)
{
if (node->value >= x)
{
/* Skip this node and its descendants, as they are all >= x . */
return;
}
printf("%d\n", node->value);
if (node->left != NULL)
smaller_than(node->left, x);
if (node->right != NULL)
smaller_than(node->right, x);
}
如果子树的根的值大于或等于x,则根据最小堆的定义,其所有后代的值也将大于或等于x。该算法不需要比其遍历的项目更深入地探索,因此它是O(k)。
当然,将此转换为数组算法是一件小事:
#define ROOT 0
#define LEFT(pos) ((pos)*2 + 1)
#define RIGHT(pos) ((pos)*2 + 2)
void smaller_than(int x, int pos, int heap[], int count)
{
/* Make sure item exists */
if (pos >= count)
return;
if (heap[pos] >= x)
{
/* Skip this node and its descendants, as they are all >= x . */
return;
}
printf("%d\n", heap[pos]);
smaller_than(x, LEFT(pos), heap, count);
smaller_than(x, RIGHT(pos), heap, count);
}
答案 2 :(得分:1)
作为数组的实现是无关紧要的,你仍然可以进行自上而下的树搜索。只是不使用“经典”指针,而是需要计算相应的子节点索引。
在此过程中,从顶部进行递归搜索,并在当前节点大于x的每个分支上停止递归。这通常会删除很多你不需要检查的值。
使用k返回值O(k)显然是最好的情况。如果您的顶级节点是< = x,则立即开始获得结果。如果它更大,你就完成了 - 结果是空的。
从那里你可以在子树下一直得到结果,直到用值>命中分支。 X。你需要做最多2 * k检查来修剪那些分支,所以对我来说它总是看起来像O(k)。