糟糕的树设计,数据结构

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 属性。

以上是关于糟糕的树设计,数据结构的主要内容,如果未能解决你的问题,请参考以下文章

逻辑数据库设计 - 单纯的树(递归关系数据)(转)

逻辑数据库设计 - 单纯的树(递归关系数据)

一个糟糕的表设计

java 设计模式实战,合成模式之神奇的树结构

java 设计模式实战,合成模式之神奇的树结构

设计递归算法,将以“孩子-兄弟链表”表示的树中的结点数据按层次逐一输出。