c++实现kd树
#ifndef _KD_TREE_H_
#define _KD_TREE_H_ #include <memory>
#include <vector>
#include <algorithm>
#include <iostream>
#include <functional>
#include <iomanip>
#include <stack>
#include <array>
#include <cfloat>
#include <cmath> namespace zstd
{
struct threeD_node
{
double value[];//value[0] = x, value[1] = y, value[2] = z
threeD_node()
{
value[] = 0.0;
value[] = 0.0;
value[] = 0.0;
}
threeD_node(double x, double y, double z)
{
value[] = x;
value[] = y;
value[] = z;
}
};
struct sort_for_threeD_node
{
int dimension;
sort_for_threeD_node(int d) :dimension(d){}
bool operator ()(const threeD_node& lhs, const threeD_node& rhs)
{
if (dimension == )
return lhs.value[] < rhs.value[];
else if (dimension == )
return lhs.value[] < rhs.value[];
else if (dimension == )
return lhs.value[] < rhs.value[];
else
std::cerr << "error in sort_for_threeD_node"<< std::endl;
return false;
}
}; struct kd_node
{
double value[];//value[0] = x, value[1] = y, value[2] = z
int kv;//0=x, 1=y, 2=z
bool is_leaf;
kd_node *left, *right;
kd_node()
{
value[] = value[] = value[] = 0.0;
kv = -;
is_leaf = false;
left = nullptr;
right = nullptr;
}
kd_node(const kd_node& node)
{
value[] = node.value[];
value[] = node.value[];
value[] = node.value[];
kv = node.kv;
is_leaf = node.is_leaf;
left = node.left;
right = node.right;
}
kd_node& operator = (const kd_node& node)
{
value[] = node.value[];
value[] = node.value[];
value[] = node.value[];
kv = node.kv;
is_leaf = node.is_leaf;
left = node.left;
right = node.right; return *this;
}
};
class kd_tree
{
private:
std::shared_ptr<kd_node> root;
std::vector<threeD_node>& vec_ref;
const int k = ;
const int cspace = ;
private:
int get_dimension(int n) const
{
return n % k;
}
void sort_by_dimension(std::vector<threeD_node>& v, int dimension, int l, int r);
kd_node* build_tree(int left, int right, kd_node* sp_node, int dimension);
void _print_tree(kd_node* sp, bool left, int space); double distance(const kd_node& lhs, const threeD_node& rhs);
public:
explicit kd_tree(std::vector<threeD_node>&);
kd_tree(const kd_tree&) = delete;
kd_tree operator = (const kd_tree&) = delete;
~kd_tree(){}; void print_tree();
std::vector<threeD_node> find_k_nearest(int k, const threeD_node& D);
};
void kd_tree::sort_by_dimension(std::vector<threeD_node>& v, int dimension, int l, int r)
{
sort_for_threeD_node s(dimension);
std::sort(v.begin()+l, v.begin()+r, s);
}
kd_tree::kd_tree(std::vector<threeD_node>& v) :vec_ref(v)
{
if (vec_ref.empty())
root = nullptr;
else
{
root = std::make_shared<kd_node>();
int dimension = ;
sort_by_dimension(vec_ref, dimension, , vec_ref.size());
int mid = vec_ref.size() / ;
root->value[] = vec_ref[mid].value[];
root->value[] = vec_ref[mid].value[];
root->value[] = vec_ref[mid].value[];
root->kv = dimension;
if (vec_ref.size() == )//root is leaf
{
root->left = nullptr;
root->right = nullptr;
root->is_leaf = true;
}
else
{
root->is_leaf = false;
root->left = build_tree(, mid - , root->left, get_dimension(dimension + ));
root->right = build_tree(mid + , vec_ref.size() - , root->right, get_dimension(dimension + ));
}
}
}
kd_node* kd_tree::build_tree(int left, int right, kd_node* sp_node, int dimension)
{
dimension = get_dimension(dimension);
sort_by_dimension(vec_ref, dimension, left, right + ); if(left == right)//leaf
{
sp_node = new kd_node();
sp_node->value[] = vec_ref[left].value[];
sp_node->value[] = vec_ref[left].value[];
sp_node->value[] = vec_ref[left].value[];
sp_node->kv = dimension;
sp_node->is_leaf = true;
sp_node->left = nullptr;
sp_node->right = nullptr; return sp_node;
}
else if (left < right)
{
int mid = left + (right - left) / ;
sp_node = new kd_node();
sp_node->value[] = vec_ref[mid].value[];
sp_node->value[] = vec_ref[mid].value[];
sp_node->value[] = vec_ref[mid].value[];
sp_node->kv = dimension;
sp_node->is_leaf = false;
sp_node->left = nullptr;
sp_node->right = nullptr; sp_node->left = build_tree(left, mid - , sp_node->left, get_dimension(dimension + ));
sp_node->right = build_tree(mid + , right, sp_node->right, get_dimension(dimension + )); return sp_node;
}
return nullptr;
}
void kd_tree::_print_tree(kd_node* sp, bool left, int space)
{
if (sp != nullptr)
{
_print_tree(sp->right, false, space + cspace);
std::cout << std::setw(space);
std::cout << "(" <<
sp->value[] << ", " <<
sp->value[] << ", " <<
sp->value[] << ")";
if (left)
std::cout << "left";
else
std::cout << "right";
if (sp->is_leaf)
std::cout << "------leaf";
std::cout << std::endl;
_print_tree(sp->left, true, space + cspace);
}
else
std::cout << std::endl;
}
void kd_tree::print_tree()
{
std::cout << "kd_tree : " << std::endl;
if (root != nullptr)
{
int space = ;
_print_tree(root->right, false, space + cspace);
std::cout << "(" <<
root->value[] << ", " <<
root->value[] << ", " <<
root->value[] << ")root" << std::endl;
_print_tree(root->left, true, space + cspace);
}
}
double kd_tree::distance(const kd_node& lhs, const threeD_node& rhs)
{
double v0 = lhs.value[] - rhs.value[];
double v1 = lhs.value[] - rhs.value[];
double v2 = lhs.value[] - rhs.value[];
return sqrt(v0 * v0 + v1 * v1 + v2 * v2);
}
std::vector<threeD_node> kd_tree::find_k_nearest(int ks, const threeD_node& D)
{
std::vector<threeD_node> res;
const kd_node *ptr_kd_node;
if (static_cast<std::size_t>(ks) > vec_ref.size())
return res;
std::stack<kd_node> s;
struct pair
{
double distance;
kd_node node;
pair() :distance(DBL_MAX), node(){ }
bool operator < (const pair& rhs)
{
return distance < rhs.distance;
}
};
std::unique_ptr<pair[]> ptr_pair(new pair[ks]);
//pair *ptr_pair = new pair[ks]();
if (!ptr_pair)
exit(-); if (!root)//the tree is empty
return std::vector<threeD_node>();
else
{
if (D.value[root->kv] < root->value[root->kv])
{
s.push(*root);
ptr_kd_node = root->left;
}
else
{
s.push(*root);
ptr_kd_node = root->right;
}
while (ptr_kd_node != nullptr)
{
if (D.value[ptr_kd_node->kv] < ptr_kd_node->value[ptr_kd_node->kv])
{
s.push(*ptr_kd_node);
ptr_kd_node = ptr_kd_node->left;
}
else
{
s.push(*ptr_kd_node);
ptr_kd_node = ptr_kd_node->right;
}
} while (!s.empty())
{
kd_node popped_kd_node;//±£´æ×îеĴÓÕ»ÖÐpop³öµÄkd_node
popped_kd_node = s.top();
s.pop();
double dist = distance(popped_kd_node, D);
std::sort(&ptr_pair[], &ptr_pair[ks]);
if (dist < ptr_pair[ks-].distance)
{
ptr_pair[ks-].distance = dist;
ptr_pair[ks-].node = popped_kd_node;
} if (abs(D.value[popped_kd_node.kv] - popped_kd_node.value[popped_kd_node.kv])
>= dist)//Ô²²»ºÍpopped_kd_nodeµÄÁíÒ»°ëÇøÓòÏཻ
continue;
else//Ô²ºÍpopped_kd_nodeµÄÁíÒ»°ëÇøÓòÏཻ
{
if (D.value[popped_kd_node.kv] < popped_kd_node.value[popped_kd_node.kv])//right
{
kd_node *ptr = popped_kd_node.right;
while (ptr != nullptr)
{
s.push(*ptr);
if (D.value[ptr->kv] < ptr->value[ptr->kv])
ptr = ptr->left;
else
ptr = ptr->right;
}
}
else//left
{
kd_node *ptr = popped_kd_node.left;
while (ptr != nullptr)
{
s.push(*ptr);
if (D.value[ptr->kv] < ptr->value[ptr->kv])
ptr = ptr->left;
else
ptr = ptr->right;
}
}
}
}//end of while
for(int i = ; i != ks; ++i)
res.push_back(threeD_node(ptr_pair[i].node.value[],
ptr_pair[i].node.value[], ptr_pair[i].node.value[]));
}//end of else
//delete ptr_pair;
return res;
} }//end of namespace zstd #endif
#include <string>
#include <iostream>
#include <new>
#include <fstream>
#include <vector>
#include <algorithm>
#include <ctime> #include "trie_tree.h"
#include "kd_tree.h" int main()
{
std::vector<zstd::threeD_node> v, res;
v.push_back(zstd::threeD_node(, , ));//
v.push_back(zstd::threeD_node(, , ));//
v.push_back(zstd::threeD_node(, , ));//
v.push_back(zstd::threeD_node(, , ));//
v.push_back(zstd::threeD_node(, , ));//
v.push_back(zstd::threeD_node(, , ));//
v.push_back(zstd::threeD_node(, , ));//
v.push_back(zstd::threeD_node(, , ));//
v.push_back(zstd::threeD_node(, , ));//
v.push_back(zstd::threeD_node(, , ));//
v.push_back(zstd::threeD_node(, , ));//
std::cout << "size: " << v.size() << std::endl;
zstd::kd_tree tree(v);
tree.print_tree();
res = tree.find_k_nearest(, zstd::threeD_node(, , ));
std::cout << "-------" << std::endl;
std::cout << "离点(0,0,0)最近的点依次是:" << std::endl;
for (auto i : res)
{
std::cout << "(" << i.value[] << ", " << i.value[] << ", " << i.value[] << ")" << std::endl;
}
system("pause");
return ;
}


c++实现kd树的更多相关文章
- 利用KD树进行异常检测
软件安全课程的一次实验,整理之后发出来共享. 什么是KD树 要说KD树,我们得先说一下什么是KNN算法. KNN是k-NearestNeighbor的简称,原理很简单:当你有一堆已经标注好的数据时,你 ...
- 2016 ICPC青岛站---k题 Finding Hotels(K-D树)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5992 Problem Description There are N hotels all over ...
- kd树和knn算法的c语言实现
基于kd树的knn的实现原理可以参考文末的链接,都是一些好文章. 这里参考了别人的代码.用c语言写的包括kd树的构建与查找k近邻的程序. code: #include<stdio.h> # ...
- PCL点云库:Kd树
Kd树按空间划分生成叶子节点,各个叶子节点里存放点数据,其可以按半径搜索或邻区搜索.PCL中的Kd tree的基础数据结构使用了FLANN以便可以快速的进行邻区搜索.FLANN is a librar ...
- KNN算法与Kd树
最近邻法和k-近邻法 下面图片中只有三种豆,有三个豆是未知的种类,如何判定他们的种类? 提供一种思路,即:未知的豆离哪种豆最近就认为未知豆和该豆是同一种类.由此,我们引出最近邻算法的定义:为了判定未知 ...
- k临近法的实现:kd树
# coding:utf-8 import numpy as np import matplotlib.pyplot as plt T = [[2, 3], [5, 4], [9, 6], [4, 7 ...
- 从K近邻算法谈到KD树、SIFT+BBF算法
转自 http://blog.csdn.net/v_july_v/article/details/8203674 ,感谢july的辛勤劳动 前言 前两日,在微博上说:“到今天为止,我至少亏欠了3篇文章 ...
- bzoj 3489: A simple rmq problem k-d树思想大暴力
3489: A simple rmq problem Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 551 Solved: 170[Submit][ ...
- k近邻法的C++实现:kd树
1.k近邻算法的思想 给定一个训练集,对于新的输入实例,在训练集中找到与该实例最近的k个实例,这k个实例中的多数属于某个类,就把该输入实例分为这个类. 因为要找到最近的k个实例,所以计算输入实例与训练 ...
- bzoj 3053 HDU 4347 : The Closest M Points kd树
bzoj 3053 HDU 4347 : The Closest M Points kd树 题目大意:求k维空间内某点的前k近的点. 就是一般的kd树,根据实测发现,kd树的两种建树方式,即按照方差 ...
随机推荐
- iOS进阶_三方使用步骤
一.配置环境(:后为在终端输入的命令) 打开终端 查看自己电脑的Ruby环境:gem sources -l 如果环境已经是淘宝镜像了,此时不需要再进行环境的修改. 如果不是,发送gem sources ...
- week7 read
对于银弹: 在<No Silver Bullet>这篇IBM大型电脑之父佛瑞德·布鲁克斯(Fred Brooks)在1987年所发表的一篇关于软体工程的经典论文中,强调了由于软件的复杂性本 ...
- [Leetcode][JAVA] Convert Sorted Array to Binary Search Tree && Convert Sorted List to Binary Search Tree
Convert Sorted Array to Binary Search Tree Given an array where elements are sorted in ascending ord ...
- [转] MySQL 查询表数据大小的总结
一:关于mysql表数据大小 我们知道mysql存储数据文件一般使用表空间存储 当mysql使用innodb存储引擎的时候,mysql使用表存储数据分为共享表空间和独享表空间两种方式 ·共享表空间:I ...
- jsti 和EL用法注意点
今天使用stl 结合El做jsp页面展现,出现了个问题,怎么调也调不好,最后将jstl的源码拿来跟踪调了一下才明白其中的道理. 在使用jstl tag <c:forEach var=" ...
- 伪元素小tips
1.伪元素的是dom看不见的,表现为行内元素.我这里说的伪元素是指::before ::after.其他的像:first-letter :visited 则属于伪类. 2.因为dom不可见,所以伪元素 ...
- 使用gson在解析unicode时遇到的问题
之前在用gson解析的时候未记录下来,所以今天做一个小的总结, 比如遇到像这种"\u003d"的unicode的字符,我们想解码这个字符,用gson可以这样表达 Gson gson ...
- Eclipse下Android开发错误之Unable to execute dex: java.nio.BufferOverflowException. Check the Eclipse log for stack trace
升级了Android版本后,在运行应用时提示: [2013-11-27 10:37:35 - Dex Loader] Unable to execute dex: java.nio.BufferOve ...
- storysnail的Linux串口编程笔记
storysnail的Linux串口编程笔记 作者 He YiJun – storysnail<at>gmail.com 团队 ls 版权 转载请保留本声明! 本文档包含的原创代码根据Ge ...
- linux下用rpm包安装默认配置
rpm安装默认目录:数据文件:/var/lib/mysql/配置文件模板:/usr/share/mysqlmysql客户端工具目录:/usr/bin日志目录:/var/log/pid,sock文件目录 ...