我正在尝试实现树数据结构。我的树对象中的一个方法将节点与坐标相关联,同时将子节点映射到父节点&副节。
最初我给每个节点一个孩子的列表,结果证明是不正确的。因此,为了解决这个问题,我决定只使用空列表初始化节点,这就是故障开始的地方。
首先是有效的代码......
def treeSetUp(self):
'''Set tree's initial structure
For each level in treeArray
[level, leaf, [node number, parent, full, [coordinates], [centroid], [children]], [node number, leaf, full, [coordinates], [centroid], [children]], ...]'''
# Create root level & node
leaf = False
numChildren = (self.dims[0] * self.dims[1] * self.dims[2])/self.diameters[0]**3 # This maybe whay it only works for cubes
children = [(kids) for kids in xrange(numChildren)]
rootCoords = np.array([[0, 0, 0], [0, self.dims[0], 0], [self.dims[0], 0, 0], [self.dims[0], self.dims[1], 0], [0, 0, self.dims[2]], [0, self.dims[1], self.dims[2]], [self.dims[0], 0, self.dims[2]], [self.dims[0], self.dims[1], self.dims[2]]])
xCentroid = np.sum(rootCoords[:,0])/8.0
yCentroid = np.sum(rootCoords[:,1])/8.0
zCentroid = np.sum(rootCoords[:,2])/8.0
rootCentroids = [xCentroid, yCentroid, zCentroid]
rootNode = [0, None, False, rootCoords, rootCentroids, copy.copy(children)]
treeArray = []
treeArray.append([0, leaf, [rootNode]])
allCoordinates = []
allCoordinates.append(rootCoords)
allCentroids = []
allCentroids.append(rootCentroids)
for idx in xrange(self.depth):
# self.coordGenerator splits a given domain into cubes & returns the
# coordinates of each cube as well as its associated centroid
# This is done at different resolutions at different levels
levelCoordinates, levelCentroid = self.coordGenerator(idx+1)
allCoordinates.append(levelCoordinates)
allCentroids.append(levelCentroid)
nodeCount = 0
if idx == self.depth-1:
leaf = True
# Generate level's nodes
newNodes = []
for parentNode, node in enumerate(treeArray[idx][2]):
# Generate nodes's child list
children = []
for nodeNumber, child in enumerate(node[5]):
# Gereate child list
if leaf:
children = [None]
else:
numChildren = (self.diameters[idx]**3)/(self.diameters[idx+1]**3)
children = [(kids + nodeCount*numChildren) for kids in xrange(numChildren)]
# Assign coordinates to level 1 nodes else generate placeholders
if idx == 0:
nodeCoords = levelCoordinates[nodeNumber]
nodeCentroid = levelCentroid[nodeNumber]
else:
nodeCoords = []
nodeCentroid = []
newNodes.append([nodeCount, parentNode, False, copy.deepcopy(nodeCoords), copy.deepcopy(nodeCentroid), copy.copy(children)])
nodeCount += 1
newLevel = [idx+1, leaf, copy.deepcopy(newNodes)]
treeArray.append(newLevel)
# Operation find parents
for level in xrange(1, self.depth):
for childNode, centroid in enumerate(allCentroids[level+1]):
for node in treeArray[level][2]:
# bounding box of parent node
boundary = node[3]
xBound = [np.min(boundary[:,0]), np.max(boundary[:,0])]
yBound = [np.min(boundary[:,1]), np.max(boundary[:,1])]
zBound = [np.min(boundary[:,2]), np.max(boundary[:,2])]
# Is child's centroid in parents ounding box?
if (xBound[0] <= centroid[0] <= xBound[1]) and (yBound[0] <= centroid[1] <= yBound[1]) and (zBound[0] <= centroid[2] <= zBound[1]):
treeArray[level+1][2][childNode][1] = node[0] # Add parent node to child
treeArray[level+1][2][childNode][3] = allCoordinates[level+1][childNode]
treeArray[level+1][2][childNode][4] = centroid
# treeArray[level][2][node[0]][5].append(childNode) # Add child to parents list of children
break
现在代码没有......
def treeSetUp(self):
'''Set tree's initial structure
For each level in treeArray
[level, leaf, [node number, parent, full, [coordinates], [centroid], [children]], [node number, leaf, full, [coordinates], [centroid], [children]], ...]'''
# Create root level & node
leaf = False
numChildren = (self.dims[0] * self.dims[1] * self.dims[2])/self.diameters[0]**3 # This maybe whay it only works for cubes
children = [(kids) for kids in xrange(numChildren)]
rootCoords = np.array([[0, 0, 0], [0, self.dims[0], 0], [self.dims[0], 0, 0], [self.dims[0], self.dims[1], 0], [0, 0, self.dims[2]], [0, self.dims[1], self.dims[2]], [self.dims[0], 0, self.dims[2]], [self.dims[0], self.dims[1], self.dims[2]]])
xCentroid = np.sum(rootCoords[:,0])/8.0
yCentroid = np.sum(rootCoords[:,1])/8.0
zCentroid = np.sum(rootCoords[:,2])/8.0
rootCentroids = [xCentroid, yCentroid, zCentroid]
rootNode = [0, None, False, rootCoords, rootCentroids, copy.copy(children)]
treeArray = []
treeArray.append([0, leaf, [rootNode]])
allCoordinates = []
allCoordinates.append(rootCoords)
allCentroids = []
allCentroids.append(rootCentroids)
for idx in xrange(self.depth):
# self.coordGenerator splits a given domain into cubes & returns the
# coordinates of each cube as well as its associated centroid
# This is done at different resolutions at different levels
levelCoordinates, levelCentroid = self.coordGenerator(idx+1)
allCoordinates.append(levelCoordinates)
allCentroids.append(levelCentroid)
nodeCount = 0
if idx == self.depth-1:
leaf = True
# Generate level's nodes
newNodes = []
for parentNode, node in enumerate(treeArray[idx][2]):
# Generate nodes's child list
children = []
for nodeNumber, child in enumerate(node[5]):
# Gereate child list
if leaf:
children = [None]
else:
numChildren = (self.diameters[idx]**3)/(self.diameters[idx+1]**3)
children = [(kids + nodeCount*numChildren) for kids in xrange(numChildren)]
# Assign coordinates to level 1 nodes else generate placeholders
if idx == 0:
nodeCoords = levelCoordinates[nodeNumber]
nodeCentroid = levelCentroid[nodeNumber]
else:
nodeCoords = []
nodeCentroid = []
newNodes.append([nodeCount, parentNode, False, copy.deepcopy(nodeCoords), copy.deepcopy(nodeCentroid), []]) #copy.copy(children)])
nodeCount += 1
newLevel = [idx+1, leaf, copy.deepcopy(newNodes)]
treeArray.append(newLevel)
# Operation find parents
for level in xrange(1, self.depth):
for childNode, centroid in enumerate(allCentroids[level+1]):
for node in treeArray[level][2]:
# bounding box of parent node
boundary = node[3]
xBound = [np.min(boundary[:,0]), np.max(boundary[:,0])]
yBound = [np.min(boundary[:,1]), np.max(boundary[:,1])]
zBound = [np.min(boundary[:,2]), np.max(boundary[:,2])]
# Is child's centroid in parents ounding box?
if (xBound[0] <= centroid[0] <= xBound[1]) and (yBound[0] <= centroid[1] <= yBound[1]) and (zBound[0] <= centroid[2] <= zBound[1]):
treeArray[level+1][2][childNode][1] = node[0] # Add parent node to child
treeArray[level+1][2][childNode][3] = allCoordinates[level+1][childNode]
treeArray[level+1][2][childNode][4] = centroid
# treeArray[level][2][node[0]][5].append(childNode) # Add child to parents list of children
break
唯一的区别是,我没有提供错误的子节点列表,而是提供了一个空列表。
它给出的错误..
treeArray[level+1][2][childNode][1] = node[0] # Add parent node to child IndexError: list index out of range
那么为什么要添加空列表而不是占用列表更改索引?
遗憾的是,我没有权利共享其余的代码,我试图用简化的代码复制这个错误,但到目前为止还没有运气。
我怀疑这里有一些明显的东西,但是经过一天的怀疑之后盯着它,它的意义就越来越差。
答案 0 :(得分:3)
我相信如果你打印
treeArray[level+1][2][childNode]
在发生错误的行之前,您会发现代码中的[]
不起作用,并且与代码中的其他内容相同。因此,当您将...[childNode][1]
设置为有值时,如果您有错误,则会遇到同样的错误
a = []
a[1]=1
> IndexError: list assignment index out of range
在工作代码中,您会看到以下内容:
a=[4,6]
a[1]=1
print a
>[4,1]
如果你没有发送一个空列表,而是发送一个孩子的副本,那么当它尝试设置该条目时,它就会成功,因为该条目已经在列表中了,它是只是改变价值。另一方面,如果它试图设置空列表的[1]条目,那么它将失败,因为列表条目还没有存在。可以认为a[n]=x
就像提交更改a[n]
身份所需的法律形式一样。如果您为不存在的人提交表单,则该过程不起作用。要实际创建a[n]
,需要执行其他一些过程。
您应该显着简化代码。而不是列出诸如[nodeCount, parentNode, False, copy.deepcopy(nodeCoords), copy.deepcopy(nodeCentroid), []]
之类的内容,我认为你最好定义一个包含所有这些内容的对象。它将更容易调试。