【问题标题】:How to create a D-ary balanced tree in python using `networkx` python package如何使用`networkx`python包在python中创建一个D-ary平衡树
【发布时间】:2021-12-30 05:30:13
【问题描述】:

我正在尝试使用 networkx 包在 python 中生成一个 D-ary 平衡树。

    import networkx as nx
    g=nx.Graph()
    D= int(input("enter number of children of a node:"));
    L=int(input("Enter the number of levels:"));

    #variable to store the total number of nodes in the tree.
    tot_node=0;

    for i in range(0,L+1):
          tot_node=tot_node+D**i;

    for N in range(1,tot_node):
          for j in range(N,N+D):
                g.add_edge(N,j);
    
    nx.draw(g); 
    

为此,我得到了D=2L=3 的以下树。 enter image description here

有人可以指出这段代码中的错误吗?我想为任何一般的D(一个节点的分支数)构建一个平衡树。

【问题讨论】:

  • 一个问题,这是正确的定义吗:在图论中,m-ary 树(也称为 k-ary 或 k-way 树)是一个有根树,其中每个节点都没有更多比m个孩子。还有,这里的levels是什么意思?
  • @RichardKYu 按级别我的意思是说不包括根节点的树的深度。我需要一个 m-ary 平衡树,其中不包括叶节点的每个节点都应该有正好 'm' 个子节点。
  • 这张图片是你想要的 D=2 和 L=3:imgur.com/5LlV603
  • @RichardKYu 是的。
  • 您是否需要修复您的代码,或者替代实现是否可行?

标签: python graph tree binary-tree


【解决方案1】:

我再次更新了代码以确保一般情况下有效。我希望我没有让这变得比必要的更复杂,我觉得必须有一些更简单的实现,也许是依赖递归的。

无论如何,我已经产生了我认为可以接受的结果。虽然它不是您的直接代码,但我相信我已经按照您想要的基本解决方案实现了一些东西:

import matplotlib.pyplot as plt
import networkx as nx
from networkx import Graph

#We make a node class to track which node to modify (modify here means add children to.)
class Node:
  def __init__(self, node_id, has_children, not_connected):
      self.node_id = node_id
      self.has_children = has_children
      self.not_connected = not_connected

def get_min_not_connected(nodes_tracker):
    smallest = float('inf')
    for node in nodes_tracker:
        #print(f"Is the node {node.node_id} not connected:  {node.not_connected}")
        if node.node_id < smallest and node.not_connected:
            smallest = node.node_id
    return smallest-1

def construction_step(G, node_id, num_children, nodes_tracker):

    #print(f"The range is {len(nodes_tracker)+1} to  {len(nodes_tracker)+num_children+1}")

    #I am just creating new Node objects to track which connections have been made here. Note how the third parameter of not connected is True.


    nodes_tracker = nodes_tracker + [Node(i,False,True) for i in range(len(nodes_tracker)+1, len(nodes_tracker)+num_children+1)]
    for i in range(1, num_children+1):
        print(f'adding edge relation ({node_id}, {get_min_not_connected(nodes_tracker)+i})')

    #Here I am adding the child nodes to the parent ones.
        G.add_edge(node_id, get_min_not_connected(nodes_tracker)+i)
    
    for i in range(1, num_children+1):
        #print(get_min_not_connected(nodes_tracker))
        nodes_tracker[get_min_not_connected(nodes_tracker)].not_connected = False
    
    return nodes_tracker


#Hardcode inputs for your specific example.
#I am using num_children in place of your D variable.
num_children=3
L=2

G=nx.Graph()

#Create the central (initial) node and setup
total_nodes = 0

#correct formula is like 2^0+2^1+...+2^L
for i in range(0,L):
    total_nodes += num_children**i

print(total_nodes)


nodes_tracker = [Node(1,False,False)]


#Create the actual d-ary graph here.
for i in range(1, total_nodes+1):
    nodes_tracker = construction_step(G, i, num_children, nodes_tracker)

#print(len(nodes_tracker))

nx.draw(G); 
plt.show()

对于参数 D=2、L=3 的输出,我得到:

为了测试更一般的情况,我使用了 D=4,L=2,得到:

为了好玩,D=5,L=3:

它也适用于更大的 D 和 L,但图表自然看起来很丑。

感谢您对此回答的耐心等待,希望对您有所帮助。

【讨论】:

  • 感谢这种替代方式。我也做过类似的事情。我不想使用 balance_tree 函数进行编码,但我想要一些基本的和通用的方法来解决这个问题。
猜你喜欢
  • 2014-04-07
  • 1970-01-01
  • 2014-06-02
  • 1970-01-01
  • 2018-08-30
  • 1970-01-01
  • 1970-01-01
  • 2019-03-07
  • 1970-01-01
相关资源
最近更新 更多