Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 查找树中最大n个节点的算法_Algorithm_Search_Tree - Fatal编程技术网

Algorithm 查找树中最大n个节点的算法

Algorithm 查找树中最大n个节点的算法,algorithm,search,tree,Algorithm,Search,Tree,假设我们有一棵树,其中的节点包含一些数字。 我需要在这棵树上找到n个最大的数字。 我脑子里有两个算法: 1.使用BFS或DFS在树上迭代并将其节点放入数组中,然后使用快速排序作为示例对其进行排序,并返回n个第一个元素。 该方法的时间复杂度为O(| V |+| E |+| V | log | V |),空间复杂度为O(| V |) 2.第二种方法是在树上迭代,找到最大元素并将其标记n次。所以时间复杂度是O(N*(|V |+| E |)),空间复杂度也是O(|V |) 哪种解决方案更好,也许我走错了

假设我们有一棵树,其中的节点包含一些数字。 我需要在这棵树上找到n个最大的数字。 我脑子里有两个算法:

1.使用BFS或DFS在树上迭代并将其节点放入数组中,然后使用快速排序作为示例对其进行排序,并返回n个第一个元素。 该方法的时间复杂度为O(| V |+| E |+| V | log | V |),空间复杂度为O(| V |)

2.第二种方法是在树上迭代,找到最大元素并将其标记n次。所以时间复杂度是O(N*(|V |+| E |)),空间复杂度也是O(|V |)

哪种解决方案更好,也许我走错了路,有更好的解决方案?

标准选择算法不起作用

基本算法是(假设
k
是要选择的项目数)

如果需要按升序将它们从堆中移除到数组中,然后反转数组


这个算法是O(n log k),其中
n
是树中的节点数,
k
是您想要的项目数。

树是否对其节点的相对顺序提供任何保证?例如,它是一个二元搜索树,其中左子级总是小于其父级,右子级总是大于或等于它吗?不,它只是一个表示某个网络的通用树。好的,在这种情况下,它不会让您使用任何东西,所以(渐近地说)您不妨将其复制到带有DFS/BDS的数组中作为第一步。关于下一步的操作:排序和抓取前n个项目并不太糟糕,但您可以去除一个日志系数(使用简单的轴选择规则的平均时间,或使用复杂且缓慢的中位数轴选择规则的最坏情况时间)通过使用quickselect直接查找第n个最大的元素,然后简单地在数组中循环,使所有元素>=找到的元素。(重复的元素也可以处理,稍微考虑一下。)@DanAllen:这也是一个好方法,前提是不要将元素添加到排序列表(维护起来很昂贵),而是将它们插入到最小堆中。每当堆达到大小n+1时,就删除它的最小元素,这可以在O(logn)时间内完成。这保持了堆大小如果DFS本身是O(|V |+|E |)),它怎么可能是O(n log k)?@s0nicYouth:如果树有
n
节点,那么深度优先搜索是O(n)。不管你怎么描述它,它的节点数都是线性的。选择算法具有
n log k
,因为在堆中插入是
log k
,删除是
log k
,在最坏的情况下,每个项都被添加到堆中并从堆中删除。所以
2n logk
,因为我们在渐近分析中忽略了常数因子,所以它是O(n logk)。也许我问了一个愚蠢的问题,但我认为V顶点和E边的DFS时间复杂度是O(V+E),这对我来说是必要的。你为什么说它是O(n)(或O(V)是相同的)?@s0nicYouth:这取决于树的定义。我的假设是,有一棵树,其中任何节点只有一条路径。最简单的情况是二叉树,但您可以将其扩展到三叉树等,或者具有不同节点数的树。如果可以有多条路径到任何给定的节点,那么它确实是O(V+E)。在这种情况下,我描述的搜索算法将采用(V+E)进行遍历,使整个算法O((V+E)+(V log k)),仍然是O(V log k)。
create an empty min-heap
for each node (depth-first search)
    if heap.count < k
        heap.Add(node)
    else if node.Value < heap.Peek.Value()
        heap.RemoveSmallest()
        heap.Add(node)
while heap.count > 0
    output (heap.RemoveSmallest().Value)