参考: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算法的更多相关文章

  1. K-D TREE算法原理及实现

    博客转载自:https://leileiluoluo.com/posts/kdtree-algorithm-and-implementation.html k-d tree即k-dimensional ...

  2. 【数据结构与算法】k-d tree算法

    k-d tree算法 k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点 ...

  3. k-d tree算法

    k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点匹配的时候就会利用到k ...

  4. Kd Tree算法详解

    kd树(k-dimensional树的简称),是一种分割k维数据空间的数据结构,主要应用于多维空间关键数据的近邻查找(Nearest Neighbor)和近似最近邻查找(Approximate Nea ...

  5. k-d tree 学习笔记

    以下是一些奇怪的链接有兴趣的可以看看: https://blog.sengxian.com/algorithms/k-dimensional-tree http://zgjkt.blog.uoj.ac ...

  6. K-D Tree题目泛做(CXJ第二轮)

    题目1: BZOJ 2716 题目大意:给出N个二维平面上的点,M个操作,分为插入一个新点和询问到一个点最近点的Manhatan距离是多少. 算法讨论: K-D Tree 裸题,有插入操作. #inc ...

  7. [转载]kd tree

    [本文转自]http://www.cnblogs.com/eyeszjwang/articles/2429382.html k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据 ...

  8. 【学习笔记】K-D tree 区域查询时间复杂度简易证明

    查询算法的流程 如果查询与当前结点的区域无交集,直接跳出. 如果查询将当前结点的区域包含,直接跳出并上传答案. 有交集但不包含,继续递归求解. K-D Tree 如何划分区域 可以借助下文图片理解. ...

  9. 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 ...

随机推荐

  1. Lucene-Analyzer

    Lucene文本解析器实现 把一段文本信息拆分成多个分词,我们都知道搜索引擎是通过分词检索的,文本解析器的好坏直接决定了搜索的精度和搜索的速度. 1.简单的Demo private static fi ...

  2. 环信SDK与Apple Watch的结合(3)

    第3章主要介绍怎样在Watch App的页面上显示iPhone程序里的数据.主要操作的是“EMWatchOCDemo WatchKit Extension”这个文件夹,附源码EMWatchOCDemo ...

  3. ASP.NET MVC的路由

    好久没写博文了,感觉最近好像少了点动力.唉!这回就看看这个MVC的路由. 说这个路由机制其实不是MVC里面特有的,ASP.NET里面本身就有的,只不过在WebForm里面一般比较少用,而在MVC里就是 ...

  4. iostat命令

    http://www.orczhou.com/index.php/2010/03/iostat-detail/ Linux系统出现了性能问题,一般我们可以通过top.iostat.free.vmsta ...

  5. php中的不常用数组函数(一)(数组中元素的键和值对调 array_flip())

    array_flip($arr); //交换数组中的键和值. //如下所示,如果$arr中有相同的值.交换之后 会被旧的覆盖,最后一个有效. /***********array_flip(交换数组中的 ...

  6. mysql zip install

    1.Question Description: 1.1 version: mysql-5.7.11-64 1.2 form: zip file 1.3 >mysqld --install (su ...

  7. 蒙特卡洛树搜索算法(UCT): 一个程序猿进化的故事

    前言: 本文是根据的文章Introduction to Monte Carlo Tree Search by Jeff Bradberry所写. Jeff Bradberry还提供了一整套的例子,用p ...

  8. 开发机多用户 xdebug 远程调试 PhpStorm

    在公司都用的远程开发机开发,每次有错误调试就得dd(xxx)然后保存真是,让我在本地开发用惯xdebug的情何以堪,所以有了下文. 1.安装配置xdebug 直接使用pecl安装即可 # pecl i ...

  9. RAID选项

    RAID:Redundant Array Independent Disk(独立磁盘构成的具有冗余能力的阵列) 最常见的为RAID类型为:0,1,5和10:3和6很少见,但在某些环境中仍然有用. RA ...

  10. SQL数据库基础(七)

    主键 数据库主键是指表中一个列或列的组合,其值能唯一地标识表中的每一行.这样的一列或多列称为表的主键,通过它可强制表的实体完整性.当创建或更改表时可通过定义 PRIMARY KEY约束来创建主键.一个 ...