当前位置: 首页 > news >正文

四叉树和KD树

1. 简介

四叉树和KD树都是用于空间数据索引和检索的树状数据结构。它们通过将空间递归地划分为更小的区域,并存储每个区域内的点,来实现快速搜索和范围查询。

2. 四叉树

2.1 定义

四叉树是一种树状数据结构,它将二维空间递归地划分为四个相等的子区域,直到每个子区域只包含一个点或为空。每个节点代表一个矩形区域,并存储该区域内的所有点。

2.2 构建

构建四叉树的过程如下:

  1. 将整个空间划分为四个相等的子区域。
  2. 将每个点分配到相应的子区域。
  3. 递归地对每个子区域进行步骤 1 和 2,直到每个子区域只包含一个点或为空。

2.3 搜索

搜索四叉树的过程如下:

  1. 从根节点开始,检查当前节点的区域是否包含目标点。
  2. 如果包含,则递归地搜索该节点的四个子节点。
  3. 如果不包含,则搜索失败。

2.4 范围查询

范围查询是指查找所有位于给定矩形区域内的点。搜索过程与搜索单个点类似,但需要遍历所有与查询区域相交的节点。

2.5 Kotlin 代码演示


data class Point(val x: Double, val y: Double)data class Rectangle(val x: Double, val y: Double, val width: Double, val height: Double) {fun contains(point: Point): Boolean {return point.x >= x && point.x <= x + width && point.y >= y && point.y <= y + height}fun intersects(other: Rectangle): Boolean {return !(other.x + other.width < x ||other.x > x + width ||other.y + other.height < y ||other.y > y + height)}
}class QuadTree(val boundary: Rectangle, val capacity: Int = 1) {private var points: MutableList<Point> = mutableListOf()private var children: Array<QuadTree?> = arrayOfNulls(4)fun insert(point: Point): Boolean {if (!boundary.contains(point)) {return false}if (points.size < capacity) {points.add(point)return true}if (children[0] == null) {subdivide()}for (i in 0..3) {if (children[i]!!.insert(point)) {return true}}return false}private fun subdivide() {val xMid = boundary.x + boundary.width / 2val yMid = boundary.y + boundary.height / 2children[0] = QuadTree(Rectangle(boundary.x, boundary.y, xMid, yMid), capacity)children[1] = QuadTree(Rectangle(xMid, boundary.y, boundary.x + boundary.width, yMid), capacity)children[2] = QuadTree(Rectangle(boundary.x, yMid, xMid, boundary.y + boundary.height), capacity)children[3] = QuadTree(Rectangle(xMid, yMid, boundary.x + boundary.width, boundary.y + boundary.height), capacity)for (point in points) {for (i in 0..3) {if (children[i]!!.insert(point)) {break}}}points.clear()}fun query(range: Rectangle): List<Point> {val foundPoints = mutableListOf<Point>()if (!boundary.intersects(range)) {return foundPoints}for (point in points) {if (range.contains(point)) {foundPoints.add(point)}}if (children[0] != null) {for (child in children) {if (child != null) {foundPoints.addAll(child.query(range))}}}return foundPoints}
}fun main() {val boundary = Rectangle(0.0, 0.0, 10.0, 10.0)val quadTree = QuadTree(boundary, 4)val points = listOf(Point(1.0, 1.0),Point(2.0, 2.0),Point(3.0, 3.0),Point(4.0, 4.0),Point(5.0, 5.0),Point(6.0, 6.0),Point(7.0, 7.0),Point(8.0, 8.0),Point(9.0, 9.0))for (point in points) {quadTree.insert(point)}val queryRange = Rectangle(0.0, 0.0, 5.6, 4.4)val foundPoints = quadTree.query(queryRange)println("Points in range:")for (point in foundPoints) {println("(${point.x}, ${point.y})")}
}

3. KD树

3.1 定义

KD树是一种树状数据结构,它将多维空间递归地划分为两个子空间,每个子空间由一个超平面分割。每个节点代表一个超矩形区域,并存储该区域内的所有点。

3.2 构建

构建KD树的过程如下:

  1. 选择一个维度作为分割维度,并找到该维度上的中位数。
  2. 使用中位数将空间划分为两个子空间。
  3. 递归地对每个子空间进行步骤 1 和 2,直到每个子空间只包含一个点或为空。

3.3 搜索

搜索KD树的过程如下:

  1. 从根节点开始,检查当前节点的区域是否包含目标点。
  2. 如果包含,则根据目标点的坐标选择相应的子节点进行递归搜索。
  3. 如果不包含,则搜索失败。

3.4 范围查询

范围查询是指查找所有位于给定超矩形区域内的点。搜索过程与搜索单个点类似,但需要遍历所有与查询区域相交的节点。

3.5 Kotlin 代码演示


// Define the Point class
internal class Point(var x: Double, var y: Double) {override fun toString(): String {return "($x, $y)"}
}// Define the k-d tree node class
internal class KDNode(var point: Point) {var left: KDNode? = nullvar right: KDNode? = null
}// Define the k-d tree class
internal class KDTree(points: List<Point>) {private val root: KDNode?init {this.root = buildTree(points, 0)}private fun buildTree(points: List<Point>, depth: Int): KDNode? {if (points.isEmpty()) {return null}val axis = depth % Kval sortedPoints = points.sortedWith(Comparator { a, b ->if (axis == 0) {a.x.compareTo(b.x)} else {a.y.compareTo(b.y)}})val medianIndex = sortedPoints.size / 2val node = KDNode(sortedPoints[medianIndex])node.left = buildTree(sortedPoints.subList(0, medianIndex), depth + 1)node.right = buildTree(sortedPoints.subList(medianIndex + 1, sortedPoints.size), depth + 1)return node}fun rangeSearch(lowerLeft: Point, upperRight: Point): List<Point> {val result: MutableList<Point> = ArrayList()rangeSearch(root, lowerLeft, upperRight, 0, result)return result}private fun rangeSearch(node: KDNode?,lowerLeft: Point,upperRight: Point,depth: Int,result: MutableList<Point>) {if (node == null) {return}val point = node.pointif (point.x >= lowerLeft.x && point.x <= upperRight.x && point.y >= lowerLeft.y && point.y <= upperRight.y) {result.add(point)}val axis = depth % Kif (axis == 0) {if (lowerLeft.x <= point.x) {rangeSearch(node.left, lowerLeft, upperRight, depth + 1, result)}if (upperRight.x >= point.x) {rangeSearch(node.right, lowerLeft, upperRight, depth + 1, result)}} else {if (lowerLeft.y <= point.y) {rangeSearch(node.left, lowerLeft, upperRight, depth + 1, result)}if (upperRight.y >= point.y) {rangeSearch(node.right, lowerLeft, upperRight, depth + 1, result)}}}companion object {private const val K = 2 // 2-dimensional space, e.g., x, y, z, t, etc}
}// Example usage
object KDTreeExample {@JvmStaticfun main(args: Array<String>) {val points: MutableList<Point> = ArrayList()points.add(Point(0.5, 0.5))points.add(Point(1.0, 1.0))points.add(Point(1.5, 1.5))points.add(Point(2.0, 2.0))points.add(Point(3.0, 3.0))val kdTree = KDTree(points)val lowerLeft = Point(0.0, 0.0)val upperRight = Point(1.5, 2.2)val result = kdTree.rangeSearch(lowerLeft, upperRight)for (point in result) {println(point)}}
}

5. 注意事项

  • 四叉树和KD树的构建和搜索时间复杂度取决于数据的分布和查询区域的大小。
  • 四叉树和KD树都是用于空间数据索引和检索的有效数据结构。四叉树适用于二维空间,而KD树适用于多维空间。
  • 在实际应用中,可以使用各种优化技术来提高性能,例如使用边界框、预分配内存等。
  • 对于高维数据,KD树的性能可能会下降,可以使用其他数据结构,例如球树或随机投影树。

相关文章:

四叉树和KD树

1. 简介 四叉树和KD树都是用于空间数据索引和检索的树状数据结构。它们通过将空间递归地划分为更小的区域&#xff0c;并存储每个区域内的点&#xff0c;来实现快速搜索和范围查询。 2. 四叉树 2.1 定义 四叉树是一种树状数据结构&#xff0c;它将二维空间递归地划分为四个…...

C语言中结构体使用.与->访问成员变量的区别

文章目录 前言点运算符&#xff08;.&#xff09;箭头运算符&#xff08;->&#xff09;总结 前言 在C语言中&#xff0c;. 和 -> 都是用来访问结构体成员的运算符&#xff0c;但它们的使用场景和含义有所不同。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面…...

计算机二级Access选择题考点

在Access中&#xff0c;若要使用一个字段保存多个图像、图表、文档等文件&#xff0c;应该设置的数据类型是附件。在“销售表"中有字段:单价、数量、折扣和金额。其中&#xff0c;金额单价x数量x折扣&#xff0c;在建表时应将字段"金额"的数据类型定义为计算。若…...

人工智能历史与现状

1 人工智能历史与现状 1.1 人工智能的概念和起源 1.1.1 人工智能的概念 人工智能 (Artificial Intelligence ,AI)是一门研究如何使计算机 能够模拟人类智能行为的科学和技术,目标在于开发能够感知、理解、 学习、推理、决策和解决问题的智能机器。人工智能的概念主要包含 以…...

【git使用一】windows下git下载、安装和卸载

目录 &#xff08;1&#xff09;下载安装包 &#xff08;2&#xff09;安装git &#xff08;3&#xff09;安装验证 &#xff08;4&#xff09;卸载git &#xff08;1&#xff09;下载安装包 官网下载地址&#xff1a;Git 国内镜像下载地址&#xff1a;CNPM Binaries Mir…...

JVM 类加载器的工作原理

JVM 类加载器的工作原理 类加载器&#xff08;ClassLoader&#xff09;是一个用于加载类文件的子系统&#xff0c;负责将字节码文件&#xff08;.class 文件&#xff09;加载到 JVM 中。Java 类加载器允许 Java 应用程序在运行时动态地加载、链接和初始化类。 2. 类加载器的工…...

ARM Cortex-M4 CPU指令大全:作用、原理与实例

引言 在计算机系统中&#xff0c;CPU&#xff08;中央处理器&#xff09;是执行各种指令的核心部件。ARM Cortex-M4是广泛应用于嵌入式系统中的一款处理器&#xff0c;其指令集架构&#xff08;ISA&#xff09;基于ARMv7-M。本文将介绍ARM Cortex-M4处理器中的常见指令&#x…...

Mysql学习(九)——存储引擎

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 七、存储引擎7.1 MySQL体系结构7.2 存储引擎简介7.3 存储引擎特点7.4 存储引擎选择7.5 总结 七、存储引擎 7.1 MySQL体系结构 连接层&#xff1a;最上层是一些客户…...

TFT屏幕波形显示

REVIEW 关于TFT显示屏&#xff0c;之前已经做过彩条显示&#xff1a; TFT显示屏驱动_tft驱动-CSDN博客 关于ROM IP核&#xff0c;以及coe文件生成&#xff1a; FPGA寄存器 Vivado IP核_fpga寄存器资源-CSDN博客 1. TFT屏幕ROM显示正弦波 ①生成coe文件 %% sin-cos wave dat…...

服务器无法远程桌面连接不上的问题排查与解决方案

一、问题概述 当尝试使用远程桌面协议&#xff08;RDP&#xff09;连接至服务器时&#xff0c;如果连接失败&#xff0c;这通常意味着存在一些配置问题、网络问题或服务器本身的问题。此类问题对于管理员而言&#xff0c;需要系统地进行排查和解决。 二、排查步骤 1. 检查网…...

JAVA面试题整理——内存溢出与内存泄露的区别与联系

内存溢出与内存泄露的区别与联系 在前面jvm学习整理的时候其实用过一个简单的例子了解过内存溢出&#xff0c;在jvm内存模型章节下&#xff0c;大家有兴趣的可以去看看&#xff1a;JVM初学 GC_knowwait的博客-CSDN博客 内存溢出 内存溢出&#xff08;out of memory&#xff09…...

L50--- 104. 二叉树的最大深度(深搜)---Java版

1.题目描述 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 2.思路 这个二叉树的结构如下&#xff1a; 根节点 1 左子节点 2 右子节点 3 左子节点 4 计算过程 从根节点 1 开始计算&#xff1a; 计算左子树的最大深度&#xff1a; 根节点 2&#xf…...

Linux 中 “ 磁盘、进程和内存 ” 的管理

在linux虚拟机中也有磁盘、进程、内存的存在。第一步了解一下磁盘 一、磁盘管理 &#xff08;1.1&#xff09;磁盘了解 track&#xff08; 磁道 &#xff09; &#xff1a;就是磁盘上的同心圆&#xff0c;从外向里&#xff0c;依次排序1号&#xff0c;2号磁盘........等等。…...

test_pipeline

test_pipeline 是一个测试管道&#xff08;test pipeline&#xff09;的定义。 在计算机视觉任务中&#xff0c;通常需要对输入图像进行一系列的预处理操作&#xff0c;以便将其适配到模型的输入要求或提高模型的性能。测试管道就是用于定义这些预处理操作的一系列步骤。 在给…...

使用甲骨文云arm服务器安装宝塔时nginx无法卸载

使用甲骨文云arm服务器安装宝塔 其他环境都能安装上 唯独nginx安装完不运行 卸载了几次以后还无法卸载了. 修复 重启都不行. 差点就重建主机了. 最后靠下面的命令 就卸载掉了 然后重装就把nginx安装好了 mv /www/server/nginx/sbin/nginx /tmp/nginx_back mv /etc/in…...

C++青少年简明教程:C++的指针入门

C青少年简明教程&#xff1a;C的指针入门 说到指针&#xff0c;就不可能脱离开内存。了解C的指针对于初学者来说可能有些复杂&#xff0c;我们可以试着以一种简单、形象且易于理解的方式来解释&#xff1a; 首先&#xff0c;我们可以将计算机内存想象成一个巨大的有许多格子的…...

Apache Doris 基础 -- 数据表设计(分层存储)

1、应用场景 未来一个重要的用例是类似于ES日志存储&#xff0c;其中日志场景中的数据是根据日期分割的。许多数据都是查询不频繁的冷数据&#xff0c;因此需要降低此类数据的存储成本。考虑到节约成本: 来自不同厂商的常规云磁盘的定价比对象存储更昂贵。Doris 集群实际在线…...

使用Spring Boot设计一套BI系统

商业智能&#xff08;Business Intelligence&#xff0c;简称BI&#xff09;系统是一种将数据转化为可操作信息&#xff0c;帮助企业进行决策支持的技术与工具的集合。随着大数据时代的到来&#xff0c;BI系统在企业中的应用变得越来越广泛。本文旨在探讨如何使用Spring Boot框…...

2024.6.12总结

今天是排毕业照的日子&#xff0c;拍照的时候并没有太过兴奋。后来受到主管说明天就能签offer了&#xff0c;这才喜极而泣。 自从得知自己面试通过后&#xff0c;我是非常高兴&#xff0c;开始幻想着今后的生活。可是&#xff0c;后面在等offer的过程中&#xff0c;我是无比的…...

1027 - 求任意三位数各个数位上数字的和

问题描述 对于一个任意的三位自然数 x &#xff0c;编程计算其各个数位上的数字之和 S 。 输入 输入一行&#xff0c;只有一个整数 x(100≤x≤999) 。 输出 输出只有一行&#xff0c;包括 1 个整数。 样例 输入 123 输出 6 以下是C实现的代码&#xff1a; 代码1 #…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

MySQL 主从同步异常处理

阅读原文&#xff1a;https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主&#xff0c;遇到的这个错误&#xff1a; Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一&#xff0c;通常表示&#xff…...

离线语音识别方案分析

随着人工智能技术的不断发展&#xff0c;语音识别技术也得到了广泛的应用&#xff0c;从智能家居到车载系统&#xff0c;语音识别正在改变我们与设备的交互方式。尤其是离线语音识别&#xff0c;由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力&#xff0c;广…...

ZYNQ学习记录FPGA(一)ZYNQ简介

一、知识准备 1.一些术语,缩写和概念&#xff1a; 1&#xff09;ZYNQ全称&#xff1a;ZYNQ7000 All Pgrammable SoC 2&#xff09;SoC:system on chips(片上系统)&#xff0c;对比集成电路的SoB&#xff08;system on board&#xff09; 3&#xff09;ARM&#xff1a;处理器…...

6.9本日总结

一、英语 复习默写list11list18&#xff0c;订正07年第3篇阅读 二、数学 学习线代第一讲&#xff0c;写15讲课后题 三、408 学习计组第二章&#xff0c;写计组习题 四、总结 明天结束线代第一章和计组第二章 五、明日计划 英语&#xff1a;复习l默写sit12list17&#…...