糟糕的树设计,数据结构
Posted
技术标签:
【中文标题】糟糕的树设计,数据结构【英文标题】:Bad Tree design, Data Structure 【发布时间】:2021-10-02 06:49:21 【问题描述】:我尝试制作一棵树作为我的数据结构课程的一部分。该代码有效,但速度极慢,几乎是课程接受时间的两倍。我没有数据结构和算法方面的经验,但我需要优化程序。如果有人有任何提示、建议、批评,我将不胜感激。
树不一定是二叉树。
代码如下:
import sys
import threading
class Node:
def __init__(self,value):
self.value = value
self.children = []
self.parent = None
def add_child(self,child):
child.parent = self
self.children.append(child)
def compute_height(n, parents):
found = False
indices = []
for i in range(n):
indices.append(i)
for i in range(len(parents)):
currentItem = parents[i]
if currentItem == -1:
root = Node(parents[i])
startingIndex = i
found = True
break
if found == False:
root = Node(parents[0])
startingIndex = 0
return recursion(startingIndex,root,indices,parents)
def recursion(index,toWhomAdd,indexes,values):
children = []
for i in range(len(values)):
if index == values[i]:
children.append(indexes[i])
newNode = Node(indexes[i])
toWhomAdd.add_child(newNode)
recursion(i, newNode, indexes, values)
return toWhomAdd
def checkHeight(node):
if node == '' or node == None or node == []:
return 0
counter = []
for i in node.children:
counter.append(checkHeight(i))
if node.children != []:
mostChildren = max(counter)
else:
mostChildren = 0
return(1 + mostChildren)
def main():
n = int(int(input()))
parents = list(map(int, input().split()))
root = compute_height(n, parents)
print(checkHeight(root))
sys.setrecursionlimit(10**7) # max depth of recursion
threading.stack_size(2**27) # new thread will get stack of such size
threading.Thread(target=main).start()
编辑:
对于这个输入(第一个数字是节点数,其他数字是节点的值)
5
4 -1 4 1 1
我们期望这个输出(树的高度)
3
另一个例子:
输入:
5
-1 0 4 0 3
输出:
4
【问题讨论】:
请解释预期的输入格式,并提供示例输入和预期的输出。 所以我们有了节点的值...边在哪里定义?请画出与示例对应的树,以及边在输入中的编码方式。 【参考方案1】:看起来为一个节点提供的 值 是另一个节点(其父节点)的索引引用。问题中没有说明这一点,但是如果该假设是正确的,那么您实际上并不需要使用 Node
实例创建树。只需将输入读入一个列表(您已经这样做了),您实际上拥有在其中编码的树。
例如,列表 [4, -1, 4, 1, 1] 表示这棵树,其中标签是此列表中的索引:
1
/ \
4 3
/ \
0 2
这棵树的height——根据***给出的定义——应该是 2。但显然预期的结果是 3,这是从根到节点的最长路径上的节点数(不是边)叶,或者——换句话说——树中的层数。
使用递归的想法是正确的,但是可以自底向上(从任意节点开始),递归获取父节点的结果,然后加一加一。利用动态规划的原理,将结果存储为每个节点都在一个单独的列表中,我称之为levels
:
def get_num_levels(parents):
levels = [0] * len(parents)
def recur(node):
if levels[node] == 0: # this node's level hasn't been determined yet
parent = parents[node]
levels[node] = 1 if parent == -1 else recur(parent) + 1
return levels[node]
for node in range(len(parents)):
recur(node)
return max(levels)
主要代码可以是你所拥有的:
def main():
n = int(int(input()))
parents = list(map(int, input().split()))
print(get_num_levels(parents))
【讨论】:
谢谢。这是正确的,代码有效。我也原谅自己没有在问题中澄清它。我还有另一个问题:是什么让我的实施如此缓慢?这是一个完全错误的方法吗?提前谢谢你 这不是一个完全错误的方法。它只是有很多开销:树的创建需要一些时间来处理大量输入。对于每个节点,需要创建children
列表以允许您使用自上而下的方法(您的递归沿着树向下,而我的向上)。另请注意,您的 Node 实例具有未使用的 value
属性。以上是关于糟糕的树设计,数据结构的主要内容,如果未能解决你的问题,请参考以下文章