从数据列表构建一棵树

时间:2021-02-21 04:55:12

标签: python python-3.x tree hierarchical-clustering

假设我有一个如下所示的数字列表,

a = [1,23,5,72,3,5,15,7,78,1,5,77,23]

现在我需要根据这些数据构建一棵树。

<块引用>
  1. 根据自定义函数par将数据集分成两部分。我们称这两个部分为 a0、a1。
  2. 分别对a0、a1应用函数par,得到a00、a01、a11、a12。
  3. 重复这个过程,直到结束节点只剩下一个数字。
  4. 对于每个末端节点,我们有一个“二进制代码”,如“0010100”,其中 0 代表左,1 代表在每个特定步骤中的右。

我试图使用如下所示的树类,但一开始就被卡住了。

class Node(input):
    def __init__(self, data):
        self.data = data
        self.left = '*'
        self.right = '*'

2 个答案:

答案 0 :(得分:1)

class Node(input):
    def __init__(self, data, path='0'):
        self.path = path # 0 means left, 1 means right
        if len(data) = 1:
            self.value = data[0] # this assumes the leaf is a list with single data, rather than the data itself
        else:
            left, right = par(data)
            left = Node(left, side+'0')
            right = Node(right, side+'1')

Node.path 为您提供二进制代码。

答案 1 :(得分:1)

尚不清楚内部节点将具有哪些值。这可能并不重要,但您可以始终分配属于该特定子树的数据数组中的第一个值。

“二进制代码”就像是从根到节点的导航路径。因此,对于您提供的数据,我们希望像这样的树:

value:                                   1
path:                       ____________ "" ________ 
                           /                        \
value:                    1                         15
path:                  __ 0 __                 _____ 1 _______
                      /       \               /               \
value:              1         72             15                1
path:               00        01             10             __ 11 __
                   /  \      /  \           /  \           /        \
value:            1   23    72   3         15   7         1          77
path:            000  001   010  011      100  101       110         111
                     /  \       /  \          /  \       /  \       /   \
value:              23   5     3    5        7    78    1    5     77   23
path:              0010 0011  0110 0111    1010  1011  1100 1101  1110 1111

您可以使用一个简单的 Node 类,它可以存储值和路径:

class Node:
    def __init__(self, value, path, left=None, right=None):
        self.value = value
        self.path = path
        self.left = left
        self.right = right

par 函数会做这样的事情:

def par(data):
    i = len(data) // 2
    return (data[:i], data[i:]) if i else ()

当只有一个数据元素时,if..else 运算符用于返回一个空列表。这在主函数中很有用:

def maketree(data, path=""):
    return Node(data[0], path, *(
        maketree(part, path + str(i)) for i, part in enumerate(par(data))
    ))

这将枚举由 par 返回的部分并将这些部分传递给递归调用(如果返回了任何部分)。同时,递归调用得到一个路径字符串,该字符串扩展了 0 或 1(即枚举的索引)。

示例调用:

a = [1,23,5,72,3,5,15,7,78,1,5,77,23]
root = maketree(a)

# Output the properties of one particular node:
node = root.left.left.right.left
print("value: {}, path: {}".format(node.value, node.path))
# Outputs: "value: 23, path: 0010"