参考: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. thread_fork/join并发框架1

    一.线程并发控制  Thread.Executor.ForkJoin和Actor  1.裸线程      Runnable接口,调用.start()开始,没有现成的API来结束线程,你需要自己来实现, ...

  2. 字符串 --- KMP Eentend-Kmp 自动机 trie图 trie树 后缀树 后缀数组

    涉及到字符串的问题,无外乎这样一些算法和数据结构:自动机 KMP算法 Extend-KMP 后缀树 后缀数组 trie树 trie图及其应用.当然这些都是比较高级的数据结构和算法,而这里面最常用和最熟 ...

  3. P6 Professional Installation and Configuration Guide (Microsoft SQL Server Database) 16 R1

    P6 Professional Installation and Configuration Guide (Microsoft SQL Server Database) 16 R1       May ...

  4. Fluent Nhibernate and Stored Procedures

    sql:存储过程 DROP TABLE Department GO CREATE TABLE Department ( Id INT IDENTITY(1,1) PRIMARY KEY, DepNam ...

  5. PowerDesigner工具箱(palette)如何打开

    我使用的PowerDesigner是15.1版本的,其他版本的操作可能会有所不同 我们在使用PowerDesigner的时候,有时候可能会不小心把悬浮的工具箱隐藏掉,就是下面这个东西 怎么显示出来呢, ...

  6. ThoughtWorks.QRCode生成二维码

    首先引用需要的dll,此处使用的是ThoughtWorks.QRCode.dll,网上可以找到对应的,此处也有一份,点击下载 http://files.cnblogs.com/files/ives/T ...

  7. [Architecture Pattern] Repository实作查询功能

    [Architecture Pattern] Repository实作查询功能 范例下载 范例程序代码:点此下载 问题情景 在系统的BLL与DAL之间,加入Repository Pattern的设计, ...

  8. django使用笔记

    django的具体使用可以看官方手册http://djangobook.py3k.cn,这里主要记录使用django中遇到的问题. 1.中文编码问题. 因为我们用到的东西基本上都有中文,在settin ...

  9. CSS Hack(转)

    做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我们会极不情愿的使用这个不太友好的方式来达到大家要求的页面表现.我个人是不太推荐使用hack的,要知道 ...

  10. ArcGIS快捷键导出

    在以前的文章中说过怎样恢复ArcGIS默认界面.今天同事的电脑用ArcMap打开数据后,移动或缩放数据时莫名的闪动. 于是使用排除法来查找原因:(1)先以为是数据的原因,换个数据还是有问题:(2)后以 ...