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树的两种建树方式,即按照方差 ...
随机推荐
- Linux系统MySQL开启远程连接
1.远程连接上Linux系统,确保Linux系统已经安装上了MySQL数据库.登陆数据库.mysql -uroot -p(密码). 2.创建用户用来远程连接 GRANT ALL PRIVILEGES ...
- Testng之使用@DataProvider注解做数据驱动【转】
原文:http://www.jianshu.com/p/8e333a0ec42a 前两天学了一下@DataProvider,今天有时间总结一下.testng很强大,提供了很多注解,其中利用@DataP ...
- java-多线程新特性
Java定时器相关Timer和TimerTask类 每个Timer对象相对应的是单个后台线程,用于顺序地执行所有计时器任务TimerTask对象. Timer有两种执行任务的模式,最常用的是sched ...
- linux sort,uniq,cut,wc命令详解
linux sort,uniq,cut,wc命令详解 sort sort 命令对 File 参数指定的文件中的行排序,并将结果写到标准输出.如果 File 参数指定多个文件,那么 sort 命令将这些 ...
- wireshark常用过滤规则
wireshark常用过滤规则:(Filter中输入过滤规则)1.源ip过滤:ip.src==1.1.1.1 (过滤源ip为1.1.1.1的包) 2.目的ip过滤:ip.d ...
- 怎样让.bat文件开机自启动
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\R ...
- SqlServerProxy的一些资料
SqlServerProxy的一些资料 下载地址:http://files.cnblogs.com/files/lyhabc/SqlServerProxy.rar 1.特性及实现原理 SqlServe ...
- Linux计划任务crontab运行脚本不正确的问题
问题的由来 写好的程序希望在崩溃之后能够自启动,于是利用linux的crontab功能,添加一个计划任务,每分钟执行一个脚本查看需要监控的进程是否还在,如果不在则启动之,否则不做任何事情.这么一个简单 ...
- SWT: 发起事件 post event
有很多学习SWT的同志遇到过一类需求,为某些控件添加了诸如MouseListener.KeyListener之类的监听,然后呢,希望使用代码模拟鼠标.键盘来执行点击.按键等操作. 首先说明一点,这是可 ...
- 【腾讯bugly干货】QQ空间直播秒开优化实践
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址为:http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=1204&am ...