首页 > 其他分享 >【博客】K-D树

【博客】K-D树

时间:2024-03-19 16:23:32浏览次数:22  
标签:结点 wd int mid 博客 中位数 维度

K-D树

前言

kd-tree(k-dimensional树的简称),是一种对k维空间中的实例点进行存储以便对其进行快速检索的树形数据结构。主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索)

好像跟没说一样

K-D树其实是每个结点为K维数值点的二叉树

每个结点将某一维划分成两部分

一部分为左子树

一部分为右子树

所以说,当\(k=1\)时,kd树每个点都只划分这一维,其实是二叉搜索树


在我们算法竞赛中,通常\(k=2\)

下面这棵树就是\(k=2\)的

image

它的结点交替地分了一维和二维 就像这样

image

红线是按照根结点\((7,2)\)的x维分的

蓝线是结点\((7,2)\)的左右子结点\((5,4)\) \((9,6)\)的y维分的

下次再按子节点的x维

......

这就是K-D树的一种建树方法:每一维交替建树

那么我们就开始说如何建树


操作

建树

K-D树建树的一般过程为:

  1. 选择某个维度
  2. 取数据在该维度的中位数(可以使左右子树的大小相等)作为分割的线
  3. 将小于中位数的数据点放到左子树
  4. 将大于等于中位数的数据点放到右子树

这就引出了两个问题

  1. 如何选择维度
  2. 如何计算中位数

划分维度的选择

有三种方法

  1. k维交替建树(离线)

就是按顺序 每一维依次划分

上面的例子就是这种方法 按照x和y依次划分的

操作的时候可以用取余运算

第 \(i\) 层按照 \(i\) \(mod\) \(k\) 维划分

  1. 最大方差法(离线)

第一种方法并不是最优的

对于一组数据 方差越大 数据越分散(初中数学

所以从方差大的维度分 可以更优

不过 谁(sei)还这么做啊

梅姐又附体

3.动态插入法(在线)

把每一个点依次插入 不平衡就拍扁重建 插入操作在后面

为了方便,在算法竞赛中,最常用的是第一种方法


计算中位数

有个stl就可以计算(狂喜)

nth_element(ps+1,ps+mid,ps+r,cmp);

表示对\(ps\)数组中下表为\([l,r)\)的元素按cmp的规则重新布置(没排序),使得\(ps[mid]\)存放着中位数,小于等于中位数的放在\([l,mid]\)中(没排序),大于中位数的放在\([mid+1,r]\)中(没排序)


之后我们就可以建树了

代码长介样

跟线段树好像

int build(int l,int r,int wd)
{
    if(l>r)return 0;
    int mid=(l+r)>>1,k=newnode();
    WD=wd;//每次按照当前维度排序
    nth_element(p+l,p+mid,p+r+1,cmp);
    t[k].pt=p[mid];
    t[k].lc=build(l,mid-1,wd^1);
    t[k].rc=build(mid+1,r,wd^1);
    update(k);
    return k;
}

插入

类似于BST的插入

到每一维判断该是左右哪个子树就好

void ins(int &k,point tmp,int wd)
{
    if(!k)//新建节点
    {
        k=newnode();
        t[k].lc=t[k].rc=0;
        t[k].pt=tmp;
        update(k);
        return ;
    }
    if(tmp.x[wd]<=t[k].pt.x[wd])ins(t[k].lc,tmp,wd^1);
    else ins(t[k].rc,tmp,wd^1); 	//判断应该插入进左子树还是右子树中
    update(k);
}

但是插入多了就会不平衡

所以可以像替罪羊树一样设一个平衡因子

对于看不惯的不平衡的直接拍扁重建

不得不提某人的逆天发言

不写替罪羊 当点多了的时候直接把整棵树重建


还有查找k远点 最近点等操作 跟具体题有关了

大概就写完了

撒花撒花


附例题

P4148 简单题

P2093 [国家集训队] JZPFAR


引用来源

kd-tree_百度百科 (baidu.com)

K-D树_k-d tree-CSDN博客

K-D Tree - OI Wiki (oi-wiki.org)

【模板】K-D Tree - ShuraEye

还有书

标签:结点,wd,int,mid,博客,中位数,维度
From: https://www.cnblogs.com/zysssss/p/18083252

相关文章

  • 【博客】【入门级】递归
    递归有部分结论代码题目来自网络在文后有链接侵删前言什么是递归?函数反复调用自身即是递归举个栗子递归我在这篇博客里写了这篇博客的链接像不像套娃举个正经栗子比如我们算\(n\)的阶乘\(f(n)\)(阶乘就是\(1*2*3*4*...*n\))以\(f(6)\)为例\(f(6)\)=>\(6\)*$......
  • 新电脑 个人博客迁移
    安装和配置所需要的软件安装Git客户端,安装过程省略,一般默认下一步    下载地址:Git客户端    这个无脑下一步即可无需配置安装nodeJS,安装过程省略,一般默认下一步    下载地址:nodeJS    配置看这位大佬教程:地址拷贝个人博客文件夹中,部......
  • 将博客搬至CSDN
    New·Object将博客搬至CSDN在数字时代的浪潮中,我始终如一地维护着自己的一方网络空间。从最初的个人网站到现在的CSDN博客,每一次的变迁都记录着我的成长与变化。今天,我想和大家分享一下将博客搬迁至CSDN的决定背后的故事,以及这个决定给我带来的一系列连锁反应。记得最初,我的博......
  • 推荐一个博客园皮肤:awescnb-theme-geek
    参考文章:我的所有做法都是参考本篇文章1.安装主题首先进入到博客后台设置:1.设置皮肤为customer,并且打开JS权限2.勾选禁用模板默认CSS3.复制粘贴配置代码(共三处)页面定制CSS代码#loading{bottom:0;left:0;position:fixed;right:0;top:0;z-index:9999;background-co......
  • 初出茅庐的小李博客之串口屏开发一个音乐控制器UI
    串口屏介绍串口屏通常指的是一种带有串口接口的显示屏,可以通过串口与其他设备进行通信和控制。这种屏幕通常具有独立的控制器和显示功能,可以直接接入主控系统,实现信息的显示和交互。开发步骤准备UI素材准备了100张音量的图标,这里面还遇到了个小问题,这么多图片如何批量......
  • Gitlab+Jenkins+Docker+Harbor+K8s集群搭建CICD平台(持续集成部署Hexo博客Demo)
    目录涉及内容:一、CICD服务器环境搭建1、docker环境安装(1)、拉取镜像,启动并设置开机自启(2)、配置docker加速器2、安装并配置GitLab(1)、创建共享卷目录(2)、创建gitlab容器(3)、关闭容器修改配置文件(4)、修改完配置文件之后。直接启动容器(5)、相关的git命令(针对已存在的文件夹)3、安装配......
  • 大家觉得2024了,还有必要搭建自己的博客吗?
    其实,这个问题我之前也纠结了很久了,现在各种自媒体平台都适合记录生活,但是,这些都是公开的,就感觉在裸奔一样,没有安全感和隐私感,而个人博客就可以规避这一点,比如可以做一个个人用的知识库,资料库,家庭照片等,只要自己记住网址,不公开,那么相当是比较安全的。你觉得呢,欢迎在评论区说下你......
  • 哇!什么情况?这么好看的个人博客首页,还这么简单,这简直就是为呆呆的我学习量身准备的
    在这个万物vue的年代,网页设计越来越框架化。上网搜个资料学习学习吧,咵咵咵,“游泳健身,vue了解一下”我只是想简单地学个html,js啊!怎么就这么复杂!曾几何时,在网上找个网页模板,纯纯的html不带一点儿复杂的东西,最多加点儿jquery。我上面加个头就能当jsp的课后作业了。虽然这种东西......
  • 博客,好久不见!
    我是22年本科毕业,目前研二在读。不得不说,计算机的行情是真卷啊,尤其是Java开发,但奈何Java的岗位还是多呀,所以打算就业方向还是Java,这就要开卷了。谈到就业,有一份实习经历真的会对正式就业有很大帮助,不论是直接暑期转正还是再面其他地方,都会是很大的优势。我最近也开始准备找实习......
  • 【halo】博客系统从部署到访问
    【halo】博客系统从部署到访问部署本文采用docker-compose的方式进行部署,可以有效避免一些莫名其妙的问题halo支持多种数据库方式进行部署,这里采用的是PSQL方式进行部署,其他数据库部署方式可以参考文档docker-compose.yamlhaloports:端口映射。修改第一个......