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 ...
随机推荐
- 环信SDK与Apple Watch的结合(2)
这一篇主要是介绍怎么拖apple watch上的相关页面,附源码EMWatchOCDemo. 需要在工程中的“EMWatchOCDemo WatchKit App”中进行操作,该文件夹的结构如图 Wa ...
- ASP.NET MVC使用jQuery无刷新上传
昨晚网友有下载了一个jQuery无刷新上传的小功能,他尝试搬至ASP.NET MVC应用程序中去,在上传死活无效果.Insus.NET使用Teamviewer远程桌面,操作一下,果真是有问题.网友是说 ...
- 一些JavaScript题目
在JavaScript中,运行下面代码,sum的值是(). var sum=0;for(i=1;i<10;i++){if(i%5==0)break;sum=sum+i;} A. 40B. 50C ...
- (转) 关于在IE6下 无法跳转问题
之前在项目,用到超链接,在ie下没有问题,但是到了ie6,居然发现点击事件不起作用, 真不可思议,以前都没注意到,后来网上搜了下,问题就出在这个void(0)上!现把网上的资料整理了下. <a ...
- [moka学习笔记]yii2.0 rules的用法(收集,不定期更新)
public function rules(){ return [ ['title','required','message'=>'标题不能为空'], ['title','string','mi ...
- 那些教程没有的php3-命名空间
php.net (PHP 5 >= 5.3.0, PHP 7) 定义命名空间 虽然任意合法的PHP代码都可以包含在命名空间中,但只有以下类型的代码受命名空间的影响,它们是:类(包括抽象类和tra ...
- 【Effective Java】2、构造参数过多的时候
package cn.xf.cp.ch02.item2; /** * * 功能:当我们的构造参数有很多,超出可控范围的时候,用build模式 时间:下午8:25:05 文件:NutritionFact ...
- 【JVM】2、关于jdk7的MethodHandle类
关于MethodHandle类,这个类是在jdk1.7之后加入的,这个类的作用类似函数指针的意思 这个类中有一个方法 这里我的jdk有一个问题,就是我在进行MethodHandle操作的时候,我们会发 ...
- Orchard中文版源码下载
本版本基于Orchard1.7.2修改: 新增Bootstrap主题 新增中文语言包 增加了对Sqlite.Orchard数据库的支持 优化工程,减少临时符号生成,增加工程效率 和一些BUG的修正 默 ...
- ASP.NET页面动态添加js脚本
有时我们需要生成自己的JavaScript代码并在运行时动态添加到页面,接下来我们来看一下如何将生成的JavaScript代码动态添加到ASP.NET页面. 为了添加脚本,要将自定义的脚本在一个字符串 ...