我正在尝试获得一种有效的算法来计算Python中用于大型数据集的树的高度。我使用的代码适用于小型数据集,但是对于非常大的数据集需要花费很长时间(100,000个项目),所以我试图找出优化它的方法,但是我遇到了问题。对不起,如果它看起来像一个真正的新手问题,我对Python很新。
输入是列表长度和值列表,每个列表项指向其父项,列表项-1指示树的根。所以输入:
5
4 -1 4 1 1
答案是3 - 树是:({key:1,children:[{key:3},{key:4,children:[{key:0,{key:2}]}]}
这是我到目前为止的代码:
import sys, threading
sys.setrecursionlimit(10**7) # max depth of recursion
threading.stack_size(2**25) # new thread will get stack of such size
class TreeHeight:
def read(self):
self.n = int(sys.stdin.readline())
self.parent = list(map(int, sys.stdin.readline().split()))
def getChildren(self, node, nodes):
parent = {'key': node, 'children': []}
children = [i for i, x in enumerate(nodes) if x == parent['key']]
for child in children:
parent['children'].append(self.getChildren(child, nodes))
return parent
def compute_height(self, tree):
if len(tree['children']) == 0:
return 0
else:
max_values = []
for child in tree['children']:
max_values.append(self.compute_height(child))
return 1 + max(max_values)
def main():
tree = TreeHeight()
tree.read()
treeChild = tree.getChildren(-1, tree.parent)
print(tree.compute_height(treeChild))
threading.Thread(target=main).start()
首先,虽然python实际上是一种很棒的通用语言,但对大型数据集使用原始python并不是很有效。考虑使用pandas,NumPy,SciPy或许多伟大的alternatives之一。
第二,如果你关心树的高度,你的树就是一次写一次读。您只需更改读取输入的代码,不仅可以填充树,还可以测量高度。
当你不希望你的树在创建后改变时,这种态度是有道理的
使用DFS可以避免递归调用中的堆栈溢出。在遍历期间使用标记来了解级别的结束。
from collections import defaultdict
def compute_height(root, tree):
q = ListQueue()
q.enqueue(root)
q.enqueue('$')
height = 1
while not q.isEmpty():
elem = q.dequeue()
if elem =='$' and not q.isEmpty():
elem = q.dequeue()
height+=1
q.enqueue('$')
for child in tree[elem]:
q.enqueue(child)
return height
tree = defaultdict(list)
parents = [4, -1, 4, 1, 1]
for node,parent in enumerate(parents):
tree[parent].append(node)
root = tree.pop(-1)[0]
print(compute_height(root, tree))