K-D树 C++实现

算法(1):KD树的原理与基本代码 由于在做项目时遇到平面内最近点求解的问题,需要用到KD树简化算法,减少计算资源,因此本文记录这个过程中学到的知识。 阅读详情

       K-D树主要是为了实现机器学习算法中的K近邻算法,单纯的K-D树只能实现最近邻,但是结合优先队列就可以实现K近邻了,这里只是把K-D树简单的实现了一下,经过简单测试,暂时没有发现重大bug。

#ifndef KDTREE_H
#define KDTREE_H


#include <cassert>
#include <algorithm>
#include <cstddef>
#include <vector>
#include <cmath>
#include <iostream>
using ::std::vector;
using ::std::cout;
using ::std::endl;

namespace sx {

  typedef float DataType;
  typedef unsigned int UInt;

  struct Feature {
    vector<DataType> data;
    int id;

    Feature() {}
    Feature(const vector<DataType> & d, int i)
      : data(d), id(i) {}
  } /* optional variable list */;

  template <UInt K>
    class KDTree {
    public:
      KDTree();
      virtual ~KDTree();
      KDTree(const KDTree & rhs);

      const KDTree & operator = (const KDTree & rhs);

      void Clean();
      void Build(const vector<Feature> & matrix_feature);

      int FindNearestFeature(const Feature & target) const;
      int FindNearestFeature(const Feature & target,
                             DataType & min_difference) const;

      void Show() const;

    private:
      struct KDNode {
        KDNode * left;
        KDNode * right;
        Feature feature;
        int depth;

        KDNode(const Feature & f, KDNode * lt, KDNode * rt, int d)
          : feature(f), left(lt), right(rt), depth(d) {}
      } /* optional variable list */;

      KDNode * root_;

      struct Comparator {
        int index_comparator;

        Comparator(int ix)
          : index_comparator(ix) {}

        bool operator () (const Feature & lhs, const Feature & rhs) {
          return lhs.data[index_comparator] < rhs.data[index_comparator];
        }
      } /* optional variable list */;

      KDNode * Clone(KDNode * t) const;

      void Clean(KDNode * & t);
      void SortFeature(vector<Feature> & features, int index);
      void Build(const vector<Feature> & matrix_feature,
                 KDNode * & t, int depth);

      DataType Feature2FeatureDifference(const Feature & f1,
                                         const Feature & f2) const;
      int FindNearestFeature(const Feature & target,
                             DataType & min_difference, KDNode * t) const;

      void Show(KDNode * t) const;
    };

  template <UInt K>
    KDTree<K>::
    KDTree()
    : root_(NULL) {}

  template <UInt K>
    KDTree<K>::
    ~KDTree() {
      Clean();
    }

  template <UInt K>
    KDTree<K>::
    KDTree(const KDTree & rhs) {
      *this = rhs;
    }

  template <UInt K>
  const KDTree<K> & KDTree<K>::
    operator = (const KDTree & rhs) {
      if (this != &rhs) {
        Clean();
        root_ = Clone(rhs.root_);
      }
      return *this;
    }

  template <UInt K>
    void KDTree<K>::
    Clean() {
      Clean(root_);
    }

  template <UInt K>
    void KDTree<K>::
    Build(const vector<Feature> & matrix_feature) {
      if (matrix_feature.size() != 0) {
        assert(matrix_feature[0].data.size() == K);
      }
      Build(matrix_feature, root_, 0);
    }

  template <UInt K>
    int KDTree<K>::
    FindNearestFeature(const Feature & target) const {
      DataType min_difference;
      return FindNearestFeature(target, min_difference);
    }

  template <UInt K>
    int KDTree<K>::
    FindNearestFeature(const Feature & target, DataType & min_difference) const {
      min_difference = 10e8;
      return FindNearestFeature(target, min_difference, root_);
    }

  template <UInt K>
    void KDTree<K>::
    Show() const {
      Show(root_);
      return ;
    }


  template <UInt K>
    typename KDTree<K>::KDNode * KDTree<K>::
    Clone(KDNode * t) const {
      if (NULL == t) {
        return NULL;
      }
      return new KDNode(t->feature, t->left, t->right, t->depth);
    }


  template <UInt K>
    void KDTree<K>::
    Clean(KDNode * & t) {
      if (t != NULL) {
        Clean(t->left);
        Clean(t->right);
        delete t;
      }
      t = NULL;
    }

  template <UInt K>
    void KDTree<K>::
    SortFeature(vector<Feature> & features, int index) {
      sort(features.begin(), features.end(), Comparator(index));
    }

  template <UInt K>
    void KDTree<K>::
    Build(const vector<Feature> & matrix_feature, KDNode * & t, int depth) {
      if (matrix_feature.size() == 0) {
        t = NULL;
        return ;
      }
      vector<Feature> temp_feature = matrix_feature;
      vector<Feature> left_feature;
      vector<Feature> right_feature;

      SortFeature(temp_feature, depth % K);

      int length = (int)temp_feature.size();
      int middle_position = length / 2;

      t = new KDNode(temp_feature[middle_position], NULL, NULL, depth);

      for (int i = 0; i < middle_position; ++i) {
        left_feature.push_back(temp_feature[i]);
      }

      for (int i = middle_position + 1; i < length; ++i) {
        right_feature.push_back(temp_feature[i]);
      }

      Build(left_feature, t->left, depth + 1);
      Build(right_feature, t->right, depth + 1);

      return ;
    }

  template <UInt K>
    DataType KDTree<K>::
    Feature2FeatureDifference(const Feature & f1, const Feature & f2) const {
      DataType diff = 0.0;
      assert(f1.data.size() == f2.data.size());
      for (int i = 0; i < (int)f1.data.size(); ++i) {
        diff += (f1.data[i] - f2.data[i]) * (f1.data[i] - f2.data[i]);
      }
      return sqrt(diff);
    }

  template <UInt K>
    int KDTree<K>::
    FindNearestFeature(const Feature & target, DataType & min_difference,
                       KDNode * t) const {
      if (NULL == t) {
        return -1;
      }

      DataType diff_parent = Feature2FeatureDifference(target, t->feature);
      DataType diff_left = 10e8;
      DataType diff_right = 10e8;

      int result_parent = -1;
      int result_left = -1;
      int result_right = -1;

      if (diff_parent < min_difference) {
        min_difference = diff_parent;
        result_parent = t->feature.id;
      }

      if (NULL == t->left && NULL == t->right) {
        return result_parent;
      }

      if (NULL == t->left /* && t->right != NULL */) {
        result_right = FindNearestFeature(target, diff_right, t->right);
        if (diff_right < min_difference) {
          min_difference = diff_right;
          result_parent = result_right;
        }
        return result_parent;
      }

      if (NULL == t->right /* && t->left != NULL */) {
        result_left = FindNearestFeature(target, diff_left, t->left);
        if (diff_left < min_difference) {
          min_difference = diff_left;
          result_parent = result_left;
        }
        return result_parent;
      }

      int index_feature = t->depth % K;
      DataType diff_boundary =
        fabs(target.data[index_feature] - t->feature.data[index_feature]);

      if (target.data[index_feature] < t->feature.data[index_feature]) {
        result_left = FindNearestFeature(target, diff_left, t->left);
        if (diff_left < min_difference) {
          min_difference = diff_left;
          result_parent = result_left;
        }
        if (diff_boundary <
            Feature2FeatureDifference(target, t->left->feature)) {
          result_right = FindNearestFeature(target, diff_right, t->right);
          if (diff_right < min_difference) {
            min_difference = diff_right;
            result_parent = result_right;
          }
        }
      } else {
        result_right = FindNearestFeature(target, diff_right, t->right);
        if (diff_right < min_difference) {
          min_difference = diff_right;
          result_parent = result_right;
        }
        if (diff_boundary <
            Feature2FeatureDifference(target, t->right->feature)) {
          result_left = FindNearestFeature(target, diff_left, t->left);
          if (diff_left < min_difference) {
            min_difference = diff_left;
            result_parent = result_left;
          }
        }
      }
      return result_parent;
    }

  template <UInt K>
    void KDTree<K>::Show(KDNode * t) const {
      cout << "ID: " << t->feature.id << endl;
      cout << "Data: ";
      for (int i = 0; i < (int)t->feature.data.size(); ++i) {
        cout << t->feature.data[i] << " ";
      }
      cout << endl;
      if (t->left != NULL) {
        cout << "Left: " << t->feature.id << " -> " << t->left->feature.id << endl;
        Show(t->left);
      }
      if (t->right != NULL) {
        cout << "Right: " << t->feature.id << " -> " << t->right->feature.id << endl;
        Show(t->right);
      }
      return ;
    }

} /* sx */



#endif /* end of include guard: KDTREE_H */

      下面是测试的main.cc文件

// =============================================================================
//
//       Filename:  main.cc
//
//    Description:  K-D Tree
//
//        Version:  1.0
//        Created:  04/11/2013 04:28:02 PM
//       Revision:  none
//       Compiler:  g++
//
//         Author:  Geek SphinX(Perstare et Praestare), geek.sphinx@zoho.com
//   Organization:  Hefei University of Technology
//
// =============================================================================

#include "KDTree.h"
#include <vector>
using namespace sx;
using namespace std;

int main(int argc, char *argv[]) {
  KDTree<2> kdtree;
  vector<Feature> vf;
  int idx = 0;
  for (int i = 0; i < 5; ++i) {
    for (int j = 0; j < 5; ++j) {
      vector<DataType> vd;
      vd.push_back(i);
      vd.push_back(j);
      vf.push_back(Feature(vd, idx++));
    }
  }
  kdtree.Build(vf);
  kdtree.Show();
  Feature target;
  int n;
  DataType x, y;
  cin >> n;
  while (n--) {
    cin >> x >> y;
    vector<DataType> vd;
    vd.push_back(x);
    vd.push_back(y);
    target = Feature(vd, 0);
    DataType md;
    int t = kdtree.FindNearestFeature(target, md);
    cout << "Result is " << t << endl;
    for (int i = 0; i < (int)vf[t].data.size(); ++i) {
      cout << vf[t].data[i] << " ";
    }
    cout << endl;
    cout << "Minimum Difference is " << md << endl;
  }
  return 0;
}


数据结构与算法C++实现精读:链表、K-d树与基数排序 数据结构与算法是计算机科学的核心基础,也是技术面试和工程实践中无法回避的硬技能。数组、链表、树等基础结构在不同场景下各有优劣,理解它们在随机访问、插入删除、查找上的复杂度差异,是做出正确选型的前提。排序与搜索算法同样关键,快速排序的平均性能优势、基数排序如何突破比较排序的下限,都值得深入推敲。图算法如BFS和并查集则反映了将抽象问题建模为最短路径或连通性问题的通用思路。本内容围绕一套C/C++实现的算法参考代码,逐行解析链表操作、K-d树构建、基数排序、二分搜索、词梯BFS以及并查集优化等经典实现,通过具体 阅读详情

相关推荐

Qt下k-d树的建立和最邻近点查询算法实现

k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构。主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索)。本代码实现了图形界面下最邻近点查找,简单易懂,适用于计算几何初学者。如需介绍文档,加qq:1257690927。

手写Kd树(C++模板非递归实现)

本文实现的Kd树实现参考了高翔博士的书《自动驾驶与机器人中的slam技术从理论到实践》;高博士原书中是递归形式实现的,本文改写成了while循环的形式,避免了特大规模点云时的栈溢出问题,并且通过C++无类型模板参数,理论上可以实现广义上的无穷维点云的最近邻匹配。

我爱调试 1658

国产麒麟系统PXE安装-UEFI引导

注意: 适用uefi引导 适用x86_64架构 一键部署脚本扣我 1.上传ISO到PXE服务器,拷贝ISO文件 # mkdir /kylin_iso # mount -o loop Kylin-Server-10-SP1-Release-Build04-20200711-x86_64.iso /kylin_iso/ 2.配置http,获取安装源 # yum -y install httpd # mkdir /var/www/html/{ks,kylin} # 注意一定是"/kylin_iso/

河静 5056

K-D树数据结构介绍及C++实现

什么是K-D树? K-D树是把K维空间中的点组织起来的空间划分数据结构,与四叉树不同的是,K-D树对空间的划分不是按照某种固定模式进行的,对空间的划分更有效可参考上一篇博客:有详细的k-d树介绍和搜索方式 K-D树数据结构介绍以下图片也是K-D树的介绍,本篇主要贴出c++实现代码: C++实现K-D树一丶kdtree.h//kdtree.h #pragma once

蘇丶的博客 2524

逆向分析PerimeterX px3:从混淆JS到生成有效令牌的完整实战

在Web安全与数据采集领域,反自动化防护是保障服务稳定和数据安全的关键技术。其核心原理是通过收集浏览器环境指纹和用户行为特征,动态生成加密令牌来区分真人用户与自动化脚本。这项技术的工程价值在于平衡安全性与用户体验,广泛应用于电商、金融、社交等需要防止恶意爬虫和自动化攻击的场景。本文聚焦于业界广泛部署的PerimeterX px3防护方案,通过JavaScript逆向工程,深入剖析其令牌生成机制。我们将探讨如何运用动态调试、反混淆工具和算法还原等关键技术,突破px3的防护壁垒,为自动化测试和数据采集提供稳定可

diankui6178的博客 533

从零实现高精度手势检测:OpenCV+MediaPipe模型移植实战(2)(附c++完整代码)

上篇已经介绍了手掌检测的方法。本章将在手掌检测的基础上,完成手指关节的检测。

qq_37160641的博客 2667

KD-Tree(C++实现)

参考资料: https://blog.youkuaiyun.com/dymodi/article/details/46830071 https://github.com/WiseDoge/libkdtree 作为存取高维数据的一种数据结构,k-d tree 在静态查询和插入方面的效率还是很高的。本文在这里对 k-d tree 的内容作一些介绍,可能也会结合自己使用 k-d tree 的一些体验作一些点评...

Nick 7778

物联网 Mixly-智能楼道灯

一、实验目的及要求 熟悉声音及人体红外传感器用法。 二、实验原理与内容 1.使用声音传感器实现声控灯功能。 2.使用人体红外传感器实现人体检测控制灯功能。 三、实验软硬件环境 硬件:Arduino、LED灯、声音传感器、人体红外传感器 软件:Mixly IDE 四、实验过程(实验步骤、记录、数据、分析) 核心代码截图 声控灯: 人体红外检测灯: 3.实验效果图: (1)、声控灯总线连接: (1)、声控灯声音大于一某个值时灯亮,经过2秒后灯灭: (3)、人体红外检测灯连接总线: (4)、人体红外

qq_43430810的博客 1917

K-D Tree 维度空间搜索二叉树

​K-D树全称为K -Dimension Tree ,其实质是一棵二叉树。大家可能知道二叉搜索树,二叉搜索树是在一维数据里面建立的搜索树,用于更快的查找。这里的K - D树可以看作是推广到多维空间里面时对于点查找的搜索树。但是你可能有疑问,为什么不用二叉搜索树来进行多维里面的查找?因为点是不能直接比较大小的,所以这里的二叉搜索树必须另外建立一种建树规则,就形成了一种特殊的二叉搜索树即K - D 树。

这里是阿安的博客 2671

Blender入门教程-3D视图界面介绍

3D视图用于与3D场景交互,可用于各种目的,例如建模、动画、纹理绘制等。在关闭 启动画面 后,启动场景会显示在3D视口中(如果没有加载其他blend文件)。01 标题栏标题栏包含了基于当前 模式 的各种菜单和控制。

weixin_52345129的博客 2289

本地部署gradle

在部署CAS构建执行包时,如果按照CAS的官方命令gradlew clean build,如果系统没安装过gradle,这个步骤将会从网上下载gradle,但是进度非常慢,耗时很长。为了更快地完成项目构建,我们可以直接在本地部署好gradle,节省一点时间。

益添的博客 780

K-D树的算法原理与C++实现

K-D树 K-D树介绍 1.kd树本身是树结构的一种,但在节点上又不同于一般树。k-d树是每个节点都拥有k个维度数据的二叉树。二叉树是指所有非叶子节点可以视作用一个超平面把空间分区成两个半空间,节点左边的子树代表在超平面左边的点,节点右边的子树代表在超平面右边的点。 2.超平面:每个节点都与k维中垂直于超平面的那一维的维度有关。例如3维下取超平面为平面YOZ,则按照x轴划分,所有x值小于指定...

weixin_34015860的博客 569

ESXI 8.0.3 ubuntu 24.04 直通显卡P40

手把手,一步步教你直通GPU,ESXI 8.0.3 ubuntu 24.04 直通显卡P40

qq_36433118的博客 4684

C++ 版 K-D 树(kdtree)的实现——源码解析

本文解析了kd-tree的实现方式,源码为C++完成,并通过测试用例测试了该代码。

weixin_45867382的博客 3785

锂电池SOH预测 | 基于BP神经网络的锂电池SOH预测(附matlab完整源码)

锂电池SOH预测 | 基于BP神经网络的锂电池SOH预测(附matlab完整源码)

天天酷科研的博客 1114

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

推荐开源项目:kd-tree——C++实现的K-D树库

推荐开源项目:kd-tree——C++实现的K-D树库 kd-treeAn implementation of k-d tree项目地址:https://gitcode.com/gh_mirrors/kd/kd-tree 项目介绍 kd-tree 是一款用C++实现的K-D树(k-dimensional tree)库,它以头文件的形式提供,并支持多种最近邻搜索功能,包括单点最近邻搜索、K近邻搜索...

gitblog_00078的博客 1109

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

K-D树的c++代码实现

先贴上代码,具体原理后面再逐步完善 kdtree.h: #ifndef KDTREE_H_ #define KDTREE_H_ #include<cmath> #include<algorithm> #include<stack> #include<vector> #include<iostream> template<typename T> class KdTree { //定义节点结构 //----------

xululala的博客 491

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

K-D树

K-D树,即K-Dimensional Tree,是一种高维索引树型数据结构。常用于大规模高维数据空间的最邻近或者K邻 近查找,例如图像检索中高维图像特征向量的K邻近匹配,对KNN算法的优化等。   Contents      1. K-D树的基本原理    2. K-D树的改进(BBF算法)    3. K-D树的C++实现    4. K-D树的开源框架介绍     1.

ACdreamer 1万+

【HDU5126】 stars k-d树

题目大意:有$m$个操作,分两种:在指定三维坐标内加入一个点,询问指定空间内点的数量。 其中$m≤5*10^{4},1≤x,y,z≤10^9$ 这题几乎就是裸的$k-d$树啊。我们动态维护一棵$k-d$树,对于以某个节点为根的字树中,维护该子树中点的三维范围,以及该子树中点的数量。然后直接查询即可。 PS:为了保证你的程序不会变成“优秀”的$n^{2}$做法,需要写一个类似虚树暴力...

diaoyoutun2652的博客 121

【裸K-D树】BZOJ 2648

Problem Description 棋盘上原本有,n个黑棋。 有两种操作: 1 x y 插入一个黑色棋子 2 x y 输出距离这个白色棋子最近的黑色棋子距离(这里的距离是曼哈顿距离) 思路: 参考ldq大佬博客 K-D树,其实就是一个k维的搜索树。这道题k = 2而已。 #include<bits/stdc++.h> using namespace std; co

ACMer 梁剑锋 的博客 358

bzoj 2850: 巧克力王国 K-D树

题目大意 http://www.lydsy.com/JudgeOnline/problem.php?id=2850 题解 对于每个人,我们发现它能够接受的巧克力中 如果对参数分别讨论,那么一定是一个连续的区间 所以我们利用K-D划分维度,然后直接搜就好了 #include <cstdio> #include <cstring> #include <algorith...

weixin_30335575的博客 94

Bzoj2716 [Violet 3]天使玩偶

Time Limit:80 SecMemory Limit:128 MBSubmit:1423Solved:602 Description Input Output K-Dtree   依旧是模板题 1 #include<iostream> 2 #include&l...

dezhen7015的博客 4581

平面最近点对【kd树初探】

Description     给出n个点,每个点坐标为(xi,yi)。     定义距离为D(A,B)=|xA-xB|+|yA-yB|     求每个点到离它最近的点的距离 Input     第一行为一个整数N     接下来N行每行两个整数xi,yi,表示第i个点的坐标 Output     输出N行,每一行为第i个点的最近距离 Sample Inp

nikelong的博客 1428
上一篇: Ubuntu 12.04安装OpenCV
codeforces_sphinx
博客等级 码龄15年 32粉丝 75原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值