KNN算法,KD树实现

空间划分的数据结构(网格/四叉树/八叉树/BSP树/k-d树/BVH/自定义划分) 目录 网格 (Grid) 网格的应用 四叉树/八叉树 (Quadtree/Octree) 四叉树/八叉树的应用 BSP树 (Binary Space Partitioning Tree) 判断点在平面前后算法 BS... 阅读详情

自己实现的KD树KNN算法,和其他人不太一样,欢迎批评指正

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;



public class KdKnn {

    private Node buildKDTree(List<Node> nodeList,int dimen){

        if(nodeList.size()==0)
            return null;
        quicksort(nodeList,0,nodeList.size()-1,dimen);
        int median=nodeList.size()/2;
        Node root=nodeList.get(median);
        List<Node> leftRange=new ArrayList<Node>();
        List<Node> rightRange=new ArrayList<Node>();
        for(Node node: nodeList){
            if(node!=root){
                if(node.getIndex(dimen)<root.getIndex(dimen)){
                    leftRange.add(node);
                }else {
                    rightRange.add(node);
                }

            }
        }
        int newDimen=(++dimen)%2;

        root.setLeft(buildKDTree(leftRange,newDimen));
        root.setRight(buildKDTree(rightRange, newDimen));


        return root;
    }

    private void quicksort(List<Node> nodeList,int left,int right,int dimen){

        if(left<right){
            int q=partition(nodeList, left, right, dimen);
            quicksort(nodeList, left, q-1, dimen);
            quicksort(nodeList, q+1, right, dimen);
        }


    }

    private int partition(List<Node> nodeList, int left, int right,int dimen) {

        double x=nodeList.get(right).getIndex(dimen);
        int i=left-1;
        for(int j=left;j<right;j++){
            if(nodeList.get(j).getIndex(dimen)<x){
                i++;
                //交换i与j位置的节点
                Collections.swap(nodeList, i, j);


            }
        }
        Collections.swap(nodeList, i+1, right);

        return i+1;
    }

    //基本思想:从根节点开始搜索,搜索过程中顺便把搜索路径经过节点的“反向节点”加入先序队列中。搜索到达叶节点时候,这个叶节点暂时是

    //距离target节点最近的节点,计算distance。随后调整堆,按照distance的大小,小的在堆顶,只需要调整一次堆即可,即top1。

    //与堆顶元素进行比较,如果叶节点distance大于堆顶节点,则最近的节点便是堆顶元素,否则亦然。
    //总之:1、只计算叶节点          2、只检查其中一些叶节点
    //July说要把root节点放入先序队列。。。为什么要放进去?
    private Node searchKNN(Node root,Node target,int dimen){

        double Max_dist=0;

        Node nearest=null;

        List<Node> pirorList=new ArrayList<Node>();

            Node Kd_point=root;
            int max_steps=0;
            while(max_steps<200){
                int d=(dimen++)%2;              
                if(target.getIndex(d)<Kd_point.getIndex(d)){     //进入左子树

                    if(Kd_point.getRight()!=null){      //将右子树存入先序队列

                        Kd_point.getRight().setDistance(distance(target,Kd_point.getRight()));
                        pirorList.add(Kd_point.getRight());
                    }

                    Kd_point=Kd_point.getLeft();

                }else{                                          

                    if(Kd_point.getLeft()!=null){                //将左子树加入先序队列
                        Kd_point.getLeft().setDistance(distance(target,Kd_point.getLeft()));
                        pirorList.add(Kd_point.getLeft());

                    }

                    Kd_point=Kd_point.getRight();                //进入右子树
                }


                max_steps++;

                if(Kd_point.getRight()==null&&Kd_point.getLeft()==null){       //扫描到了叶节点
                    Max_dist=distance(Kd_point,target);
                    Kd_point.setDistance(Max_dist);
                    nearest=Kd_point;
                    break;
                }               
            }

            maintainHeap(pirorList);     //只调整一次堆就可以了

            if(pirorList.get(0).getDistance()<Max_dist)
                nearest=pirorList.get(0);

        return nearest;
    }

    private void maintainHeap(List<Node> pirorList) {

        for(int i=pirorList.size()/2-1;i>-1;i--){
             fixHeap(pirorList,i);
        }

    }

    private void fixHeap(List<Node> pirorList, int root) {      
        int left=2*root+1;
        int right=2*root+2;
        int min=root;
        if(left<pirorList.size()&&pirorList.get(min).getDistance()>pirorList.get(left).getDistance())
            min=left;
        if(right<pirorList.size()&&pirorList.get(min).getDistance()>pirorList.get(right).getDistance())
            min=right;
        Collections.swap(pirorList, min, root);
        if(root!=min){
            fixHeap( pirorList,  min);
        }

    }

    private double distance(Node a,Node b){
        double dist=0;
        double [] A=a.getData();
        double [] B=b.getData();
        for(int i=0;i<A.length;i++)
            dist+=Math.pow(A[i]-B[i], 2);
        return Math.sqrt(dist);
    }




    public static void main(String[] args) {
        List<Node> nodeList=new ArrayList<Node>();
        nodeList.add(new Node(new double[]{2,3}));
        nodeList.add(new Node(new double[]{5,4}));
        nodeList.add(new Node(new double[]{9,6}));
        nodeList.add(new Node(new double[]{4,7}));
        nodeList.add(new Node(new double[]{8,1}));
        nodeList.add(new Node(new double[]{7,2}));
        KdKnn nd=new KdKnn();
        Node root=nd.buildKDTree(nodeList, 0);
        Node target=new Node(new double[]{2.1,3.1});
        double [] nea=nd.searchKNN(root, target,0).getData();
        for(int i=0;i<nea.length;i++)
               System.out.println(nea[i]);      
        System.out.println(nd.searchKNN(root, target,0).getDistance());


    }

}

public class Node {
    private double data[];
    private Node left;//左子树
    private Node right;//右子树
    private double distance;



    public Node(double [] data){
        this.data=data;
    }
    public double getIndex(int index){
        return data[index];
    }

    public double[] getData() {
        return data;
    }
    public void setData(double[] data) {
        this.data = data;
    }
    public Node getLeft() {
        return left;
    }
    public void setLeft(Node left) {
        this.left = left;
    }
    public Node getRight() {
        return right;
    }
    public void setRight(Node right) {
        this.right = right;
    }
    public double getDistance() {
        return distance;
    }
    public void setDistance(double distance) {
        this.distance = distance;
    }

}

参考:

http://kubicode.me/2015/10/12/Machine%20Learning/KDTree-In-KNN/
http://blog.youkuaiyun.com/v_july_v/article/details/8203674

基于kd树的KNN算法的实现 记得大三初期,刚从大连理工大学回来,眼巴巴的望着同学各自都有着落了,就我一副“初出茅庐,不谙世事”的样子,于是不得不觍着脸厚着皮去找老师,恳求他让我去海洋所实习。他给我的第一份差事便是将几个G的图片里的数字输入到excel,我整整输了一个国庆节假日。当时就在到处询问,有没有那种算法可以让自动识别图片里的数字,存入到excel中去,想来,那时的自己也是够拼的。 如今这个自动识别数字的算法算是写出来了 阅读详情

相关推荐

K-近邻算法: k-nearest neighbor classification (kNN) 详细介绍

@创建于:2020.04.09 @修改于:2020.04.09,2024.06.22 文章目录1、kNN介绍2、k近邻法的三要素详解2.1 距离度量2.2 k值的选择2.3 分类决策规则3、k近邻法的实现:kd树4、Python实现过程5、优缺点6、常见问题 1、kNN介绍 kNN是一个基本而简单的分类算法,作为监督学习,那么KNN模型需要的是有标签的训练数据,对于新样本的类别由与新样本距离最近的k个训练样本点按照分类...

chenhepg的博客 9万+

K-d(k-dimension)Tree原理及实现(Java)

  使用BST存储2D数据有天然的缺陷,只能比较一个维度的信息,从而造成信息丢失。通常使用四叉树(QuadTree,按照空间划分区域)存储2D数据,使用八叉树(OctTree,按照空间划分区域)存储3D数据。   K-d(k-dimension)Tree是以二叉树的形式存储数据的,但它使用特殊的方式划分空间,理论上可以存储多个维度的数据,并且在最近邻搜索算法nearest()上通过剪枝,获得了较高的效率。   下面以2D kdTree为例,多维kdTree在此基础上扩展即可。 满足条件   root节点将整

weixin_43405649的博客 1118

Java实用工具集:闭包、KD树与图形算法

本文还有配套的精品资源,点击获取 简介:Java工具类库为简化编程任务提供了重要支持,本资源重点介绍了闭包工具、KD树和图形算法三大组件。闭包工具通过允许函数传递和作用域变量访问,提升代码简洁性和灵活性。KD树作为处理多维数据的空间分割结构,尤其适用于近邻搜索和高效数据操作。图形算法则解决图数据结构相关问题,如路径查找和最小生成树等,广泛应用于网络和图论问题解决中。这些工具...

weixin_35753291的博客 1177

KDTree详解及java实现

本文内容基于An introductory tutoril onkd-trees 1.KDTree介绍 KDTree根据m维空间中的数据集D构建的二叉树,能加快常用于最近邻查找(在加快k-means算法中有应用)。 其节点具有如下属性(对应第5节中的程序实现): 非叶子节点(不存储数据): partitionDimention 用于分割的维度,取...

weixin_30745553的博客 802

kd树java实现

利用Java语言实现kd树。利用快速排序找到每一维度的中位数构建Kd树。搜索Kd树时候利用K大堆维护K个最近邻的点。

C++实现K最邻近算法(机器学习 KNN KD树)

C++实现K最邻近算法, 使用KD树来实现, 在面对大量数据时可以提高搜索效率. 代码干净, 整洁, 有注释, 可直接使用.

Kd树实现K近邻算法

第三章:K近邻算法,基于kd树

weixin_52812620的博客 1193

java kd树实现

采用java实现的kd树,可以用与决策分类等

K近邻算法(KNN)【从 KNN 到 KD 树到算法实现】

K近邻算法(KNN)【从 KNN 到 KD 树到算法实现】 一、基本概念 KNN是一种基本分类和回归方法。 K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例,这K个实例的多数属于某个类,就把该输入实例分类到这个类中。(这就类似于现实生活中少数服从多数的思想) 如上图所示,有两类不同的样本数据,分别用蓝色的小正方形和红色的小三角形表示,而图正中间的那个绿色的圆所标示的数据则是待分类的数据。 如果K=3,绿色圆点的最邻近的3个点是2个红色小三角形和1个蓝色小正

wan_15的博客 643

《寻秦OL》.ani动画逆向解析:二进制结构与Unity重实现

动画文件格式是游戏资源逆向的核心入口,其本质是一组按特定规则组织的二进制数据流。理解魔数识别、字节序、字段对齐与差分编码等底层原理,是解析非标准格式的关键前提。技术价值在于绕过黑盒协议,直接从静态客户端提取可验证的原始语义;典型应用场景包括老游戏复刻、美术资产抢救、引擎跨平台迁移及教学级逆向训练。本文以《寻秦OL》的`.ani`文件为实例,深入剖析其C风格结构布局、GB2312中文命名、16位定点数旋转表示及帧主序差分存储机制,并基于C#在Unity中完成从字节流到AnimationClip的端到端重建,覆

weixin_30368981的博客 640

TDDFT计算软件Octopus学习笔记(二):基态计算(Si)

本文以硅为例,来进行基态计算。

陈啸的博客 7308

基于kd树的KNN算法原理以及python实现

基于kd树的KNN算法原理以及python实现

drdtddtrdr的博客 1067

OpenEuler22.04 快速部署Docker:华为云镜像源配置指南

本文详细介绍了在OpenEuler 22.04系统上快速部署Docker的完整流程。针对系统默认源版本老旧的问题,重点讲解了如何配置华为云镜像源以加速安装,并涵盖Docker引擎、Docker Compose的安装、服务启动验证、权限配置、镜像加速等核心步骤与常见问题排查,帮助用户高效搭建稳定的容器化开发环境。

http9protocoller的博客 174

java knn kd树_使用kd树实现knn算法

KNN算法是将待测样本与训练样本的特征进行比较,取k个与待测样本最接近的训练样本(如计算欧氏距离),其中k个样本中大多数属于哪一类别便也将待测样本分类为哪一类别(最大分类决策)。Kd树是高效的实现KNN算法的一种实现方式,其中的k代表有k个维度。Kd树的每个节点都可以看做一颗子树,他们拥有一致的属性和方法,因此kd树的构造和搜索都以递归的方式进行。首先构造节点类,每个节点都有根值、左孩子、右孩子三...

weixin_42126399的博客 363

南京理工大学计算机预推免面试(双非重点关注)

南京理工大学总体来说对双非学校比较友好,上岸率比较高,而且面试形式是线上,在预推免的过程中,可以作为重点关注的学校,但是一定要注意南理报名截止的时间,部分学校可能保研名额公示的比较晚,对于保研边缘人来说很可能会错过,我的建议是,即使不确定能否拿到保研名额,先查一下截止时间,先在系统上报名!!一旦拿到了offer,就是铁的,保底专硕,而且有很大的技巧性,一定要认真看哈!!!每个人的情况可能都不一样,如果有需要帮忙可以私我~~~

D1379951481的博客 2018

(五)深入理解Bluez协议栈之“GATT Server Profile”

上一篇介绍Bluez协议栈的了GAP Profile的实现,本章节我们继续介绍GATT Profile的实现,参考的程序是Peripheral。通过阅读它的实现代码可以发现,它广播部分是通过mgmt来实现的,然后在初始化完成之后,创建了一个L2CAP类型的socket,来负责实现GATT Server的逻辑。

1142

用kd树实现k近邻算法

构造kd树 在这里《统计学习方法》用到了平衡kd树,在学习平衡kd树之前可以先学习一下比较简单的平衡二叉树。这里我们直接按照《统计学习方法》中构造kd树的步骤来写代码: class Node: """构造节点类,节点包括当前节点data,当前节点的深度depth,当前节点的左右子节点left和right""" def __init__(self, data, depth=0, left=None, right=None): self.data = data se.

comli_cn的博客 1322

告别 DEFINE VIEW:CDS View Entity 迁移全景实战(报表迁移 + ADT 向导 + 避坑清单)

CDS迁移的关键要点与策略 CDS DDIC-based View已被标记为废弃,迁移到CDS View Entity成为必要。迁移面临的主要挑战包括激活成本、命名约束和依赖风险。ABAP 7.57及以上版本必须优先处理,否则将积累技术债务。 迁移方式主要有两种: 报表路线:适合渐进式迁移的On-Premise项目 ADT向导:适合云环境批量迁移 关键注意事项: 必须提前检查SQL View依赖关系 金额/数量字段需要显式引用单位/货币字段 建议按使用场景分批迁移 最佳实践是结合报表进行系统盘点,再通过AD

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 208

K-近邻算法原理介绍以及kd树实现K-近邻算法

K-近邻算法原理介绍以及kd树实现K-近邻算法 K近邻算法是一种常用的有监督的机器学习方法,k-近邻算法也被称为KNN算法,它可以解决分类问题,也可以解决回归问题。本文的主要内容如下: l KNN算法的原理以及优缺点 l KNN算法的三个基本要素 l KNN算法的基本实现步骤 l kd树以及kd树实现k-近邻算法 1. KNN算法的原理 KNN算法的工作原理非常简单:给定一个训练数据集,对新的输...

GUET_DM_TLL的博客 2017

使用 MATLAB/Simulink 构建一个分布式光伏-储能联合系统在配电网中的协同控制模型

本文介绍了使用MATLAB/Simulink构建分布式光伏-储能联合系统协同控制模型的方法。该系统包含光伏发电、储能、负荷和控制器等模块,通过协同控制实现能量优化管理。建模过程详细说明了从创建项目、搭建组件到实现控制策略的步骤,包括光伏特性模拟、储能参数设置和负荷需求建模。重点设计了协同控制器算法,实时调节电力分配,并展示了系统运行指标和经济效益分析。该方法为多能互补系统在配电网中的应用提供了技术验证,未来可进一步优化控制算法和场景适应性。

MHD0815的博客 310

6.Burp Suite 入门篇 —— Burp Scanner 漏洞扫描

Burp Scanner 既可以是独立的全自动扫描器,也可以在手动测试中当作强大的辅助手段,而且随着技术改进,Burp Scanner 能检测到的漏洞数量也在不断增加。Burp Scanner 功能只在 burpsuite 专业版和企业版中里有,本篇教程讲的是专业版的 Burp Scanner 用法。

YouTheFreedom的博客 1万+

KNN算法的KD树C++实现

KD树本质上是一种二叉树,它拥有具备特定排列顺序的分裂节点以便查找数据,即在二叉排序树之中,某个分裂节点左子树的值均小于分裂节点的值,而右侧均大于分裂节点的值,如果用中序遍历这棵树,它的打印顺序将是从小到大递增的顺序。当然剩下的科普就不说了,这也是在PCL库当中,最常用的轮子之一,处理点云速度非常快。另外,KNN算法是机器学习训练的一种非常有效的分类方法,手撸这个算法就显得很重要了。当然,在企业级...

weixin_42048023的博客 1168

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

浅谈KNN算法原理及python程序简单实现、KD树、球树

最近比较空闲,打算利用这一段时间理一下机器学习的一些常见的算法。第一个是KNN算法: KNN 1、原理: KNN,K-NearestNeighbor---K最近邻 K最近邻,就是K个最近的邻居的意思,说的就是每个样本都可以用它最接近的K个邻居来代表。核心思想是如果一个样本在特征空间中的K个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。 KNN算法...

u014486460的博客 2570

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

java knn kd树_基于kd树的KNN算法的实现

记得大三初期,刚从大连理工大学回来,眼巴巴的望着同学各自都有着落了,就我一副“初出茅庐,不谙世事”的样子,于是不得不觍着脸厚着皮去找老师,恳求他让我去海洋所实习。他给我的第一份差事便是将几个G的图片里的数字输入到excel,我整整输了一个国庆节假日。当时就在到处询问,有没有那种算法可以让自动识别图片里的数字,存入到excel中去,想来,那时的自己也是够拼的。如今这个自动识别数字的算法算是写出来了吧...

weixin_39865204的博客 224

kd树 寻找k近邻算法 python实现

kd树和寻找k近邻算法具体流程就不赘述了,这个链接写的很好懂https://zhuanlan.zhihu.com/p/23966698 按照链接里的算法写了k近邻的python实现 from math import sqrt class KDnode: def __init__(self, data, left, right, split): self.left ...

番茄锅涮代码 879

K近邻(KNN)算法、KD树及其python实现

knn、模型三要素、距离度量、k值选择、决策准则、kd树、python

十里清风 9286
上一篇: SVM
下一篇: 回溯法
jfhdd
博客等级 码龄16年 2粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值