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树的两种建树方式,即按照方差 ...
随机推荐
- Number of 1 Bits
class Solution { public: int hammingWeight(uint32_t n) { string aaa = toBinary(n); ; ; i < sizeof ...
- 特征处理(Feature Processing)
[本文链接:http://www.cnblogs.com/breezedeus/p/4109456.html,转载请注明出处] 我的博客主营地迁至github,欢迎朋友们有空去看看:http://br ...
- iOS开发零基础--Swift教程 数组
数组的介绍 数组(Array)是一串有序的由相同类型元素构成的集合 数组中的集合元素是有序的,可以重复出现 Swift中的数组 swift数组类型是Array,是一个泛型集合 数组的初始化 数组分成: ...
- sql server 基础语句
创建数据库 创建之前判断该数据库是否存在 if exists (select * from sysdatabases where name='databaseName') drop database ...
- 教你如何快速下载旧版本的Firefox浏览器
http://blog.csdn.net/gh0st007/article/details/18937421 更新后的ff使用过程中经常出现卡顿的现象,之前并没有出现,于是想找老版本的ff安装一下.发 ...
- mySQL中删除unique key的语法
CREATE TABLE `good_booked` ( `auto_id` int(10) NOT NULL auto_increment, `good_id` int(11) default ...
- 从RAM新建QIcon对象 / Create a QIcon from binary data
一般,QIcon是通过png或ico等图标文件来初始化的,但是如果图标资源已经在内存里了,或者一个zip压缩文件内,可以通过QPixmap作为桥梁,转换为图标. zf = zipfile.ZipFil ...
- [转]Git - 重写历史
转自http://git-scm.com/book/zh/Git-%E5%B7%A5%E5%85%B7-%E9%87%8D%E5%86%99%E5%8E%86%E5%8F%B2 重写历史 很多时 ...
- Android ViewPager 用法
Android ViewPager 用法 场景:一般第一次打开应用程序时,程序会有一个提示页来给展现应用程序都有哪些功能:或者程序更新时,又更新哪些新特性,都可以使用ViewPager Demo 描述 ...
- Python--增量循环删除MySQL表数据
需求场景: 有一业务数据库,使用MySQL 5.5版本,每天会写入大量数据,需要不定期将多表中“指定时期前“的数据进行删除,在SQL SERVER中很容易实现,写几个WHILE循环就搞定,虽然MySQ ...