简体   繁体   English

python 中的 n 元树插入算法

[英]n-ary tree insert algorithm in python

I'm trying to create sort of a nested round robin structure/tree where each child has N items.我正在尝试创建一种嵌套循环结构/树,其中每个孩子都有N个项目。 I believe this is what a n-ary tree is (the closest thing I could find for what I'm after) but I was not able to find a good python implementation and am trying to see if I can get help doing this right我相信这就是一元树(我能找到的最接近我所追求的东西),但我找不到一个好的 python 实现,我想看看我是否能得到帮助做这件事

So for example a tree of N=3 , given an initial root {"key": 1, "children": []} adding a new keys should result in this type of structure where each parent has max 3 children.因此,例如一棵N=3的树,给定一个初始根{"key": 1, "children": []}添加一个新键应该会导致这种类型的结构,其中每个父级最多有 3 个子级。

Image of how it should look它应该看起来如何的图像

I'm definitely doing this in a very odd way and this is why I need guidance in either correcting my code or using a diff method entirely.我肯定是以一种非常奇怪的方式来做这件事,这就是为什么我需要指导来纠正我的代码或完全使用 diff 方法。

Here's my approach:这是我的方法:

For a given N the max number of items for a given height follow this equation (where the root node is h=1)对于给定的 N,给定高度的最大项目数遵循此等式(其中根节点为 h=1)

N = 3
max_items = lambda n, h: int(n**(h-1) + n**h + n**(h-2))
height_map = {i: max_items(N, i) for i in range(1, 10)} # just pre compute first 10 levels for testing

# to get which index of the parent height the new item will go to, use
# here, when inserting 8 [self.count=7 -> count+1=8], the idx should equal 1 implying it should go under "3"
idx = ((self.count+1) - height_map[height-1] - 1) // self.N**(height-2)

class Tree:
    def __init__(self, N, tree):
        self.N = N
        self.count = 1
        self.tree = tree

    def add(self, item, tree=None, height=1):
        max_items = lambda n, h: int(n**(h-1) + n**h + n**(h-2))
        height_map = {i: max_items(self.N, i) for i in range(1, 10)}

        tree = tree if tree else self.tree
        if len(tree["children"]) >= self.N and height > 1:
            if (self.count+1) <= height_map[height]:
                idx = ((self.count+1) - height_map[height-1] - 1) // self.N**(height-2)
            child = tree["children"][idx]
            return self.add(item, child, height+1)
        elif len(tree["children"]) >= self.N and height == 1:
            return self.add(item, tree["children"][0], height+1)
        else:
            self.count += 1
            tree["children"].append({"key": item, "children": []})
        return tree

t = Tree(3, {"key": 1, "children": []})
for i in range (2, 8):
    t.add(i)
print(t.tree)

This following code works great up to inserting 7 but there's some error in my logic that does not let you properly add 8 and manage the next depths.下面的代码在插入 7 时效果很好,但我的逻辑中有一些错误不能让您正确添加 8 并管理下一个深度。 I don't think I'm passing the root tree correctly as I get to the lower height but can't figure out how to fix this.当我到达较低的高度时,我认为我没有正确传递根树,但不知道如何解决这个问题。

{'children': [{'children': [{'children': [], 'key': 5},
                            {'children': [], 'key': 6},
                            {'children': [], 'key': 7}],
               'key': 2},
              {'children': [], 'key': 3},
              {'children': [], 'key': 4}],
 'key': 1}

I'm not tied to the order the items are inserted either and only care about this structure but can't seem to make sense of it.我也不拘泥于插入项目的顺序,只关心这个结构,但似乎无法理解它。

Here is a simpler way of representing a 3-ary tree:这是表示三叉树的一种更简单的方法:

If you have the structure如果你有结构

               a                               0           
        /      |      \                 /      |      \    
       b       c       d               1       2       3   
      /|\     /|\     /|\             /|\     /|\     /|\  
     e f g   h i j   k l m           4 5 6   7 8 9   10 11 12 
    /|                              /|                     
   n o                             13 14                     

Represent it as a list:将其表示为列表:

[a, b, c, d, e, f, g, h, i, j,  k,  l,  m,  n,  o]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

(The second list is just the indices of the nodes) (第二个列表只是节点的索引)

For a given node at index i , it's children are at indices 3*i + 1 , 3*i + 2 and 3*i + 3 .对于索引i处的给定节点,它的子节点位于索引3*i + 13*i + 23*i + 3处。 For example, the children of node c (index 2 ) are h , i , and j at indices 7 , 8 , 9 respectively.例如,节点c (索引2 )的子9分别是8 7处的hij

For a given node (except the root node) at index i , the node's parent is at index (i - 1) / 3 .对于索引i处的给定节点(根节点除外),节点的父节点位于索引(i - 1) / 3处。 For example, parent of node i (index 8 ) is 2 .例如,节点i的父节点(索引8 )是2

To add a new node, simply append to this list, and it will become the child of a node.要添加新节点,只需将 append 加入此列表,它将成为节点的子节点。

The tree will be complete (ie filled in at every possible level), except possibly for the last level which is filled-in from left to right.该树将是完整的(即在每个可能的级别都填充),除了可能从左到右填充的最后一个级别。

Note that this tree structure is quite similar to a heap but with 3 children instead of 2.请注意,此树结构与非常相似,但有 3 个孩子而不是 2 个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM