数据结构——KD树

news2025/1/8 20:24:56

KD树(K-Dimensional Tree)是一种用于多维空间的二叉树数据结构,旨在提供高效的数据检索。KD树在空间搜索和最近邻搜索等问题中特别有用,允许在高维空间中有效地搜索数据点。
重要性质
1.分割K维数据空间的数据结构
2.是一颗二叉树
3.切分维度上,左子树值小于右子树值
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>

// 定义二维点的结构体
struct Point2D {
    double x;
    double y;
    Point2D(double _x, double _y) : x(_x), y(_y) {}
};

// 定义KD树节点
struct KDTreeNode {
    Point2D point;
    KDTreeNode* left;
    KDTreeNode* right;

    KDTreeNode(Point2D _point) : point(_point), left(nullptr), right(nullptr) {}
};

class KDTree {
private:
    KDTreeNode* root;

    // 构建KD树的递归函数
    KDTreeNode* buildKDTree(std::vector<Point2D>& points, int depth) {
        if (points.empty()) {
            return nullptr;
        }

        // 选择轴线,交替选择x和y坐标
        int axis = depth % 2;

        // 按轴线排序点
        if (axis == 0) {
            std::sort(points.begin(), points.end(), [](const Point2D& a, const Point2D& b) {
                return a.x < b.x;
            });
        } else {
            std::sort(points.begin(), points.end(), [](const Point2D& a, const Point2D& b) {
                return a.y < b.y;
            });
        }

        // 选择中间点作为节点
        int median = points.size() / 2;
        KDTreeNode* node = new KDTreeNode(points[median]);

        // 递归构建左子树和右子树
        std::vector<Point2D> leftPoints(points.begin(), points.begin() + median);
        std::vector<Point2D> rightPoints(points.begin() + median + 1, points.end());

        node->left = buildKDTree(leftPoints, depth + 1);
        node->right = buildKDTree(rightPoints, depth + 1);

        return node;
    }

    // 在KD树中查找最近邻点的递归函数
    KDTreeNode* findNearestNeighbor(KDTreeNode* node, Point2D target, int depth, KDTreeNode* best, double& bestDistance) {
        if (node == nullptr) {
            return best;
        }

        // 计算当前节点到目标点的距离
        double currentDistance = distance(node->point, target);

        // 更新最近邻点和距离
        if (currentDistance < bestDistance) {
            best = node;
            bestDistance = currentDistance;
        }

        // 选择子树
        int axis = depth % 2;
        KDTreeNode* nearSubtree;
        KDTreeNode* farSubtree;
        if (axis == 0) {
            if (target.x < node->point.x) {
                nearSubtree = node->left;
                farSubtree = node->right;
            } else {
                nearSubtree = node->right;
                farSubtree = node->left;
            }
        } else {
            if (target.y < node->point.y) {
                nearSubtree = node->left;
                farSubtree = node->right;
            } else {
                nearSubtree = node->right;
                farSubtree = node->left;
            }
        }

        // 递归搜索更近的子树
        best = findNearestNeighbor(nearSubtree, target, depth + 1, best, bestDistance);

        // 如果可能,搜索更远的子树
        if (shouldSearchFarSubtree(node, target, bestDistance)) {
            best = findNearestNeighbor(farSubtree, target, depth + 1, best, bestDistance);
        }

        return best;
    }

    // 计算两点之间的欧几里得距离
    double distance(Point2D a, Point2D b) {
        double dx = a.x - b.x;
        double dy = a.y - b.y;
        return std::sqrt(dx * dx + dy * dy);
    }

    // 检查是否需要搜索更远的子树
    bool shouldSearchFarSubtree(KDTreeNode* node, Point2D target, double bestDistance) {
        int axis = node->point.x > target.x ? 0 : 1; // 如果轴线是x,则比较x坐标;如果轴线是y,则比较y坐标
        double nodeDistance = axis == 0 ? node->point.x - target.x : node->point.y - target.y;
        return nodeDistance * nodeDistance < bestDistance;
    }

public:
    KDTree(std::vector<Point2D>& points) {
        root = buildKDTree(points, 0);
    }

    // 查找最近邻点
    Point2D findNearestNeighbor(Point2D target) {
        double bestDistance = std::numeric_limits<double>::max();
        KDTreeNode* bestNode = findNearestNeighbor(root, target, 0, nullptr, bestDistance);
        return bestNode->point;
    }
};

int main() {
    // 创建一些二维点
    std::vector<Point2D> points = {
        {2.0, 3.0},
        {5.0, 4.0},
        {9.0, 6.0},
        {4.0, 7.0},
        {8.0, 1.0},
        {7.0, 2.0}
    };

    // 构建KD树
    KDTree kdTree(points);

    // 查找最近邻点
    Point2D target(9.0, 2.0);
    Point2D nearestNeighbor = kdTree.findNearestNeighbor(target);

    std::cout << "The nearest neighbor to (" << target.x << ", " << target.y << ") is (" << nearestNeighbor.x << ", " << nearestNeighbor.y << ")" << std::endl;

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1022700.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

中期科技:智慧公厕是智慧城市管理智慧化的至佳表现

智慧公厕&#xff0c;作为智慧城市建设的一部分&#xff0c;正逐渐成为城市管理的新标杆。它不仅为城市居民提供便利&#xff0c;还深刻地改善了城市管理的效率。如中期科技「智慧公厕-智慧厕所」通过运用先进的科技手段&#xff0c;智慧公厕在优化城市管理、提升城市服务、促进…

电巢科技出席第26届西北地区电子技术与线路课程教学改革研讨会,聚焦一流课程建设!

2023年9月15日至17日&#xff0c;北方民族大学召开第26届西北地区电子技术与线路课程教学改革研讨会。本次会议围绕“梳理课程教学内容&#xff0c;改革教学方式&#xff0c;探索虚拟教研室构建方式&#xff0c;完善基层教学组织&#xff0c;推进一流课程和一流教材资源共享&am…

ip地址与网络上的其他地址有冲突吗?

ip地址相当于是计算机的号码。ip地址与网络上的其他ip地址有冲突是局域网ARP病毒攻击导致的。 ARP&#xff0c;即地址解析协议&#xff0c;实现通过IP地址得知其物理地址。 arp协议是TCP/IP协议组的一个协议&#xff0c;用于进行把网络地址翻译成物理地址(又称MAC地址)。arp病毒…

密码学【对称加密-DES\AES】

前言 在密码学中&#xff0c;加密算法分为双向加密和单向加密。单向加密包括MD5、SHA等摘要算法&#xff0c;它们是不可逆的。双向加密包括对称加密和非对称加密&#xff0c;对称加密包括AES加密、DES加密等。双向加密是可逆的&#xff0c;存在密文的密钥。AES算法是DES算法的替…

7.1、如何理解Flink中的时间语义

目录 1、如何理解Flink中的时间语义 2、实时计算时&#xff0c;应该如何选择时间语义&#xff1f; 3、时间语义与窗口的关系 1、如何理解Flink中的时间语义 flink作为流式计算引擎&#xff0c;提供了 两种时间语义 来对流式数据进行计算 事件时间(EventTime) : 事件产生的…

【架构篇】Supabase架构和功能介绍

Supabase是什么 Supabase将自己定位为Firebase的开源替代品&#xff0c;提供了一套工具来帮助开发者构建web或移动应用程序。Supabase是建立在Postgres之上的&#xff0c;Postgres是一个免费的开源数据库&#xff0c;被认为是世界上最稳定、最先进的数据库之一。Supabase对标F…

ValueError: Index contains duplicate entries,cannot reshape

项目场景&#xff1a; python-dataframe 在对行转列的时候出现 ValueError: Index contains duplicate entries,cannot reshape 问题描述 dataframe官方文档 # 为什么报错 是因为 index 和 columns 有重复值 df df.drop_duplicates(subset[foo,bar],keepfrist) df.pivot(i…

web vr3d可视化编辑工具推动VR教育应用落地和发展

VR编辑器可广泛的应用于教育教学、城市规划、室内设计、工业仿真、古迹复原、桥梁道路设计、军事模拟等行业。该软件适用性强、操作简单、功能强大、高度可视化、所见即所得&#xff0c;他的出现将给正在发展的VR产业注入新的活力。 作为企业级VR应用的一款重要工具&#xff0c…

vue模板语法上集->插值,指令,过滤器,计算属性监听属性,vue购物车

插值指令过滤器计算属性&监听属性vue购物车 1.插值 <!DOCTYPE html> <html><head><meta charset"utf-8"><script src"https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.js"></script><script src&quo…

视频汇聚/视频云存储/视频监控管理平台EasyCVR录像存储功能如何优化?具体步骤是什么?

视频云存储/安防监控EasyCVR视频汇聚平台基于云边端智能协同&#xff0c;支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发、视频集中存储等。视频监控系统EasyCVR拓展性强&#xff0c;视频能力丰富&#xff0c;具体可实现视频监控直播、视频轮播、视频录像、云存储、…

股指期权交割日大盘必跌吗?

股指期权交割日大盘必跌没有这一说法&#xff0c;股指期货的价格涨跌和交割日并无太大关系&#xff0c;临近交割日以后&#xff0c;股指价格和大盘趋于一致&#xff0c;如果价格相同的话&#xff0c;不存在下跌的可能性&#xff0c;下文揭秘股指期权交割日大盘必跌吗&#xff1…

面试算法8:和大于或等于k的最短子数组

题目 输入一个正整数组成的数组和一个正整数k&#xff0c;请问数组中和大于或等于k的连续子数组的最短长度是多少&#xff1f;如果不存在所有数字之和大于或等于k的子数组&#xff0c;则返回0。例如&#xff0c;输入数组[5&#xff0c;1&#xff0c;4&#xff0c;3]&#xff0…

部署大数据平台详细教程以及遇到的问题解答(ubuntu18.04下安装ambari2.7.3+HDP3.1.0)

节点准备: 我搭建的是3台,节点可以随意。建议最少是3台 hostname ip 角色 ubuntu-1804-1 172.21.73.53 从节点 ubuntu-1804-2 172.21.73.54 主节点 ubuntu-1804-3 172.21.73.55 从节点 一:关闭所有节点的防火墙 sudo ufw disable二:配置时钟同步NTP 所有节点安装ntp sud…

nodejs使用jsonwebtoken/jwt-decode生成jwt和解密token的方法

首先需要安装jsonwebtoken/jwt-decode依赖&#xff0c;这个就不用说了。 生成jwt的token&#xff0c;需要有一个加密用的salt&#xff0c;然后使用jwt.sign方法生成jwt token,具体如下&#xff1a; const jwt require("jsonwebtoken"); const jwtSalt "jasdo…

LinkedList相较于Arravlist的特点/优化

Arravlist底层是内存空间连续的数组&#xff0c;可以根据下标进行随机访问&#xff0c;效率比较高&#xff0c;因为在根据下标访问某一个元素时&#xff0c;并不是一个一个去查&#xff0c;而是算出来这个下标的地址&#xff0c;直接根据这个地址的指向去获取的&#xff0c;因为…

中国人民大学与加拿大女王大学金融硕士——在职读研,我们一起微笑前行

人生总有不期而遇的温暖&#xff0c;也有生生不息的希望。想要更好的生活&#xff0c;就先让生活看到最好的你。对于已经萌发在职读研的你&#xff0c;是否找到合适的院校呢&#xff1f;中国人民大学与加拿大女王大学金融硕士项目符合你的预期吗&#xff1f; 中国人民大学与加拿…

C++11的半同步半异步线程池

C11的半同步半异步线程池 简介同步队列Take函数Add函数Stop函数SyncQueue完整代码 线程池主函数测试 简介 半同步半异步线程池用的比较多&#xff0c;实现也比较简单。 其中同步层包括同步服务层和排队层&#xff0c;指的是将接收的任务排队&#xff0c;将所有的任务排队到一…

【数据分享】我国七普的乡镇(街道)人口数据(免费获取)

人口数据是我们在各项研究中都经常使用的数据&#xff01;人口数据的主要来源是人口普查&#xff0c;全国性的人口普查每十年进行一次。最近一次的人口普查是第七次全国人口普查&#xff0c;简称七普。七普统计的是2020年的人口数据。 之前我们分享过省市县三个层级的七普的人…

在业务和IT的视角中,MES管理系统有哪些重要性

在当今制造业中&#xff0c;MES生产管理系统已成为生产管理层面不可或缺的一部分。MES作为一款集成的软件解决方案&#xff0c;旨在连接企业的各个生产环节&#xff0c;实现生产计划、调度、执行和跟踪。本文将从业务和IT视角出发&#xff0c;探讨MES管理系统的重要性和实施细节…

PMP对项目管理工作有什么用?

首先&#xff0c;项目管理岗位基本是不限行业的&#xff0c;所以&#xff0c;只要是项目管理相关的岗位&#xff0c;pmp证书都是能起到效果的&#xff0c;不用担心局限性太大&#xff0c;而且&#xff0c;pmp证书是国际证书&#xff0c;无论国企还是外企&#xff0c;都是认可这…