[英]Tree-node based implementation (not dynamic array) of max heap in Python
[英]Python tree implementation - node reference
我有这段代码可以在Python中实现一棵树。 功能之一是查找下面所有节点(包括自身)的值之和,但这不起作用。
我认为原因是因为一旦创建了一个节点,便无法返回并使用Node(名称,值)访问它-这将创建具有该名称和值的新节点,而不是在节点中引用该节点。具有该名称和值的树,并具有与其链接的子级。
因此,sum_below函数仅返回节点的值。 我如何引用树中的节点:
class Node(object):
def __init__(self, name, value):
self.name = name
self.value = value
self.children = []
def add_child(self, obj):
self.children.append(obj)
def sum_below(self):
if self.children == []:
return self.value
else:
ret = self.value
for child in self.children:
ret += child.sum_below()
return ret
def __str__(self, level = 0):
ret = "\t"*level+repr(self.value)+"\n"
for child in self.children:
ret += child.__str__(level+1)
return ret
[编辑]我的问题是,一旦创建节点,我将无法引用它:
#In [2]:
Node(1,100)
parent = Node(1,100)
child = Node(2, 200)
parent.add_child(child)
#In [5]:
print parent
#Out [5]:
100
200
#In [6]:
print Node(1,100)
#Out [6]:
100
因此,您可以看到,parent和Node(1,100)没有引用相同的内容。
[编辑]
#In [5]:
parent.sum_below()
#Out[5]:
300
#In [6]:
Node(1,100).sum_below()
#Out[6]:
100
在上面的代码中,Node(1,100).sum_below()应该等于parent.sum_below(),因为它们应该引用相同的节点,但不是。
该代码似乎还可以。 我看到的唯一“不完美”之处是特殊情况:
if self.children == []: ...
根本不需要。 简化版:
def sum_below(self):
ret = self.value
for child in self.children:
ret += child.sum_below()
return ret
也会工作。 也可以通过使用sum
进一步简化:
def sum_below(self):
return (self.value +
sum(child.sum_below() for child in self.children))
为什么您没有与parent.sum_below()和Node(1,100).sum_below()获得相同的输出的问题是,“父”是Node类的对象,并且具有一个子属性,该子属性包含另一个节点对象“子”,因此它按应有的方式工作,但是当您编写Node(1,100).sum_below()时,您将创建一个新的对象,其名称属性= 1且值属性= 100并在其上调用sub_below()方法,因此它将返回本身的价值,因为尚未添加任何子项。
而且,您以后甚至无法访问此新创建的节点,因为您没有将其分配给任何变量。 为此,您应该执行以下操作:
>>>parent2 = Node(1, 100)
>>>parent2.sum_below()
100
>>>parent2.add_child(parent1)
>>>parent2.sum_below()
400
该答案仅涉及您需要通过指定名称来引用先前实例的部分(假设最多有一个具有相同名称的节点)。
我的建议是您尝试使用元类。 我知道这在Python中是一个有争议的问题,但我认为值得了解。 另外,我认为有一种更好且更Python化的方法可以执行此操作,但尽管如此,这是我的解决方案。下一个代码段可能会起作用。 (未选中!我正在用手机写信。可能需要进行一些小的调整)。
Class Metanode(object):
__nodes = {}
def __new__(cls,name,val):
if name not in Metanode.__nodes.keys():
Metanode.__nodes[name] = object.__new__(cls,name,val)
return Metanode.__nodes[name]
然后将其添加为元类:
class Node(metaclass=Metanode,object):
''' put rest of your def here '''
pass
现在,您的元类拥有一个实例字典。 每当您创建名称为“ x”的新实例时,您都会获得使用该名称命名的最后一个实例。 当然,您还需要在元类中处理这些实例的销毁(因此字典中将不包含不存在的实例的键)。
编辑 :在我的计算机中正确检查代码后,此代码无法正常工作。 但是,下面的代码完全不涉及元类,可以工作(在我的Ubuntu机器上使用python3检查):
class Node(object):
nodes={}
def new_init(self,name,val):
self.name = name
self.val = val
self.children = [ ]
def __new__(cls,name,val,*args,**kwds):
if name not in Node.nodes.keys():
Node.nodes[name] = super(Node,cls).__new__(cls,*args,**kwds)
Node.nodes[name].new_init(name,val)
return Node.nodes[name]
def __init__(self,name,val):
pass
def sum_below(self):
return self.val + sum(child.sum_below() for child in self.children)
def add_child(self,node):
if not isinstance(node,Node):
'''raise-some-exception-or-whatnot'''
self.children.append(node)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.