KD Tree算法
参考:http://blog.csdn.net/v_july_v/article/details/8203674
#!/user/bin/env python
# -*- coding:utf8 -*- __author__ = 'zky@msn.cn' import sys
import numpy
import heapq
import Queue class KDNode(object):
def __init__(self, name, feature):
self.name = name
self.ki = -1
self.is_leaf = False
self.feature = feature
self.kd_left = None
self.kd_right = None def traverse(self, seq, order='in'):
if order == 'in':
if self.kd_left:
self.kd_left.traverse(seq, order)
seq.append(self)
if self.kd_right:
self.kd_right.traverse(seq, order)
elif order == 'pre':
seq.append(self)
if self.kd_left:
self.kd_left.traverse(seq, order)
if self.kd_right:
self.kd_right.traverse(seq, order)
elif order == 'post':
if self.kd_left:
self.kd_left.traverse(seq, order)
if self.kd_right:
self.kd_right.traverse(seq, order)
seq.append(self)
else:
assert(False) class NodeDistance(object):
def __init__(self, kd_node, distance):
self.kd_node = kd_node
self.distance = distance # here i use a reversed result, because heapq can support only min heap
def __cmp__(self, other):
ret = other.distance - self.distance
if ret > 0:
return 1
elif ret < 0:
return -1
else:
return 0 def euclidean_distance(node1, node2):
assert len(node1.feature) == len(node2.feature)
sum = 0
for i in xrange(len(node1.feature)):
sum += numpy.square(node1.feature[i] - node2.feature[i])
return numpy.sqrt(sum) class KDTree(object):
# n is num of dimension
def __init__(self, nodes, n):
self.root = self.build_kdtree(nodes, n)
self.n = n def build_kdtree(self, nodes, n):
if len(nodes) == 0:
return None
max_var = 0
index = 0
for i in xrange(n):
features_n = map(lambda node : node.feature[i], nodes)
var = numpy.var(features_n)
if var > max_var:
max_var = var
index = i
sorted_nodes = sorted(nodes, key=lambda node: node.feature[index])
mid = len(sorted_nodes)/2
root = sorted_nodes[mid]
left_nodes = sorted_nodes[:mid]
right_nodes = sorted_nodes[mid+1:] root.ki = index
if len(left_nodes) == 0 and len(right_nodes) == 0:
root.is_leaf = True
root.kd_left = self.build_kdtree(left_nodes, n)
root.kd_right = self.build_kdtree(right_nodes, n)
return root def traverse_kdtree(self, order='in'):
seq = []
self.root.traverse(seq, order)
print map(lambda n : n.name, seq) # return a list of NodeDistance sorded by distance
def kdtree_bbf_knn(self, target, k):
if len(target.feature) != self.n:
return None
knn = []
priority_queue = Queue.LifoQueue()
priority_queue.put(self.root)
while not priority_queue.empty():
expl = priority_queue.get()
while expl:
ki = expl.ki
kv = expl.feature[ki] if expl.name != target.name: # ignore target node itself
# save a maybe result
distance = euclidean_distance(expl, target)
nd = NodeDistance(expl, distance)
assert len(knn) <= k
if len(knn) == k:
if distance < knn[0].distance:
heapq.heapreplace(knn, nd)
else: # len(knn) < k
heapq.heappush(knn, nd) unexpl = None
# find next expl
if target.feature[ki] <= kv: # left
unexpl = expl.kd_right
expl = expl.kd_left
else:
unexpl = expl.kd_left
expl = expl.kd_right # ignore nodes over a long distance bin
if unexpl:
# save a maybe next expl
if len(knn) < k:
priority_queue.put(unexpl)
elif (len(knn) == k) and (abs(kv - target.feature[ki]) < knn[0].distance):
priority_queue.put(unexpl)
ret = []
for i in xrange(len(knn)):
node = heapq.heappop(knn)
ret.insert(0, node)
return ret if __name__ == '__main__':
f1 = [7, 2]
f2 = [5, 4]
f3 = [9, 6]
f4 = [2, 3]
f5 = [4, 7]
f6 = [8, 1]
fx = [2, 4.5]
n1 = KDNode('f1', f1)
n2 = KDNode('f2', f2)
n3 = KDNode('f3', f3)
n4 = KDNode('f4', f4)
n5 = KDNode('f5', f5)
n6 = KDNode('f6', f6)
nx = KDNode('fx', fx) n1_distance = NodeDistance(n4, 1.5)
n2_distance = NodeDistance(n5, 3.2)
n3_distance = NodeDistance(n2, 3.04)
assert n1_distance > n2_distance
assert n1_distance > n3_distance
assert n2_distance < n3_distance tree = KDTree([n1, n2, n3, n4, n5, n6, nx], 2)
tree.traverse_kdtree('in')
knn = tree.kdtree_bbf_knn(nx, 3)
print map(lambda n : (n.kd_node.name, n.distance), knn)
KD Tree算法的更多相关文章
- K-D TREE算法原理及实现
博客转载自:https://leileiluoluo.com/posts/kdtree-algorithm-and-implementation.html k-d tree即k-dimensional ...
- 【数据结构与算法】k-d tree算法
k-d tree算法 k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点 ...
- k-d tree算法
k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点匹配的时候就会利用到k ...
- Kd Tree算法详解
kd树(k-dimensional树的简称),是一种分割k维数据空间的数据结构,主要应用于多维空间关键数据的近邻查找(Nearest Neighbor)和近似最近邻查找(Approximate Nea ...
- k-d tree 学习笔记
以下是一些奇怪的链接有兴趣的可以看看: https://blog.sengxian.com/algorithms/k-dimensional-tree http://zgjkt.blog.uoj.ac ...
- K-D Tree题目泛做(CXJ第二轮)
题目1: BZOJ 2716 题目大意:给出N个二维平面上的点,M个操作,分为插入一个新点和询问到一个点最近点的Manhatan距离是多少. 算法讨论: K-D Tree 裸题,有插入操作. #inc ...
- [转载]kd tree
[本文转自]http://www.cnblogs.com/eyeszjwang/articles/2429382.html k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据 ...
- 【学习笔记】K-D tree 区域查询时间复杂度简易证明
查询算法的流程 如果查询与当前结点的区域无交集,直接跳出. 如果查询将当前结点的区域包含,直接跳出并上传答案. 有交集但不包含,继续递归求解. K-D Tree 如何划分区域 可以借助下文图片理解. ...
- AOJ DSL_2_C Range Search (kD Tree)
Range Search (kD Tree) The range search problem consists of a set of attributed records S to determi ...
随机推荐
- Winform开发框架之字典管理模块的更新,附上最新2013年全国最新县及县以上行政区划代码sql脚本
在很多项目里面,字典管理是必备的项目模块,而这个又是比较通用的功能,因此可以单独做成一个通用字典管理,例如这个模块,可以通过集成的方式,使用在我的<Winform开发框架>.<WCF ...
- 【原创随笔】Sql2008 R2 做CQRS小结
1.做数据同步,订阅服务器只要把数据库建好就可以了,至于表和存储过程以及其它的都不管,订阅的时候会自动创建这些信息. 2.选择事务发布(如果同步表,表至少要带主键,不然不能选择) 3.在发布的时候,用 ...
- C语言字符串匹配函数
C语言字符串匹配函数,保存有需要时可以用: #include <stdio.h> #include <stdlib.h> #include <string.h> # ...
- 无法将类型为“System.Windows.Controls.SelectedItemCollection”的对象强制转换为类型“System.Collections.Generic.IList`1
在WPF中DataGrid 选择事件中获取SelectedItems 报错如下 无法将类型为“System.Windows.Controls.SelectedItemCollection”的对象强制转 ...
- 【jQuery基础学习】02 jQuery的DOM操作
DOM操作分为3个方面: DOM Core 任何一种支持DOM Core的语言都可以使用它,比如getElementById就是DOM Core操作 HTML-DOM 只能用来处理web文档 ...
- csharp: InvokeHelper
Entity Framework https://entityframework.codeplex.com/ Enterprise Library https://entlib.codeplex.co ...
- [转] 基于 Apache Mahout 构建社会化推荐引擎
来源:http://www.ibm.com/developerworks/cn/java/j-lo-mahout/index.html 推荐引擎简介 推荐引擎利用特殊的信息过滤(IF,Informat ...
- 重大发现Discuz DB层跨库映射关系表名前缀BUG
本文更新:http://www.cnblogs.com/x3d/p/3916198.html 场景: 在Discuz中创建Table模型,但该Table所在库与Discuz不在同一个库. Discuz ...
- 小白学Linux(三)--文件系统基本结构
Linux文件系统是一个倒立的单根树状结构,文件名称严格区分大小写(windows系统则是对大小写不明感的).路径用“/”分隔,跟windows的“\”不同. 这里我画了一张一般Linux系统的正常目 ...
- fibonacci数列的和取余(1)
As we know , the Fibonacci numbers are defined as follows: """" Given two numbe ...