我正在构建一个kd-tree来处理一个3D点(元组)列表。树枝离开或取决于点列表中的中值。通过对点进行排序并返回中点的索引来计算中值。至于kd树,这可以是x,y或z值,取决于树的深度(即,轴=深度%k)。
将中值添加到每个节点,并且一旦达到包含点的预定长度的列表,就将数据(即,点)添加到节点。所以只有叶节点包含数据。
下面是运行时间表(秒)
我的问题是:我想知道为什么一旦处理了10,000,000个点,树木构建就会爆发。这是由于硬件还是可能的排序功能?任何减少大量积分处理时间的帮助都将受到赞赏。
以下代码:
from operator import itemgetter
import time
def main():
time_start_r = time.clock()
points = random_points(10000)
time_finish_r = time.clock()
print "random run time = " + str(time_finish_r - time_start_r) + " sec"
time_start_t = time.clock()
k = len(points[0])
kd = KDTree()
kd.build_tree(points, 0, k)
time_finish_t = time.clock()
print "tree build = " + str(time_finish_t - time_start_t) + " sec"
time_start_l = time.clock()
print kd.getLeafCount(kd.root)
time_finish_l = time.clock()
print "leaf count = " + str(time_finish_l - time_start_l) + " sec"
time_start_d = time.clock()
count = kd.getDepth(kd.root, 0)
time_finish_d = time.clock()
print "find depth = " + str(time_finish_d - time_start_d) + " sec"
print count
def random_points(n):
points = []
for i in range(n):
x = round(100 * random.random(), 4)
y = round(100 * random.random(), 4)
z = round(100 * random.random(), 4)
points.append((x ,y, z))
return points
def median_index(points, axis):
points = sorted(points, key=itemgetter(axis))
return len(points) / 2
class Node:
def __init__(self):
self.value = None
self.left = None
self.right = None
self.points = None
def __str__(self):
return str(self.value)
class KDTree:
def __init__(self):
self.root = None
def build_tree(self, points, depth, k):
axis = depth % k
i = median_index(points, axis)
#print points
node = Node()
if self.root == None:
self.root = node
node.value = points[i][axis] #median value for x, y or z
if len(points) <= 20:
node = Node()
node.points = points
return node
else:
node.value = points[i][axis]
node.left = self.build_tree(points[:i], depth + 1, k)
node.right = self.build_tree(points[i:], depth + 1, k)
return node
def inorder(self, node):
if node == None:
return
else:
self.inorder(node.left)
if node.points is not None:
print node.points
#print node.value
self.inorder(node.right)
def getDepth(self, node, count):
if node == None:
return 0
if (node.left is None and node.right is None):
return count
else:
return self.getDepth(node.left, count + 1)
def getLeafCount(self, node):
if node is None:
return 0
if(node.left is None and node.right is None):
return 1
else:
return self.getLeafCount(node.left) + self.getLeafCount(node.right)
if __name__ == "__main__":
main()