美文网首页
KD树维护平面点集求近邻

KD树维护平面点集求近邻

作者: 学无止境1980 | 来源:发表于2019-07-17 12:14 被阅读0次

一道KD树模板题:HDU4347 The Closest M Points

AC代码:

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 50000;
const int MAXK = 5;

int n, m, K, cmpIdx;
struct Coordinate {
    int d[MAXK];
    friend bool operator < (const Coordinate &a, const Coordinate &b) {
        return a.d[cmpIdx] < b.d[cmpIdx];
    }
} o, point[MAXN];

struct Node {
    int ls, rs;
    Coordinate coordinate;
} kdTree[MAXN];
int nodeCnt;

int calc_distance(const Coordinate &a, const Coordinate &b) {
    int d = 0;
    for (int i=0; i<K; i++) d += (a.d[i] - b.d[i]) * (a.d[i] - b.d[i]);
    return d;
}

struct distance_less {
    bool operator ()(const Coordinate &a, const Coordinate &b) {
        return calc_distance(a, o) < calc_distance(b, o);
    }
}; // 自定义比较函数,按照与o点的距离排序
priority_queue <Coordinate, vector<Coordinate>, distance_less > Q; // 与o的距离的大根堆
stack <Coordinate> S;

void push(const Coordinate &p) {
    Q.push(p);
    if (Q.size() > m) Q.pop();
} // 仅保留与o点距离较小的m个点

int build_kdTree(int l, int r, int idx) {
    if (l >= r) return 0;
    int m = (l + r) >> 1;
    cmpIdx = idx;
    nth_element(point + l, point + m, point + r); // 可以忽略坐标值相等的情况

    int ret = nodeCnt++;
    kdTree[ret].coordinate = point[m];
    kdTree[ret].ls = build_kdTree(l, m, (idx + 1) % K);
    kdTree[ret].rs = build_kdTree(m + 1, r, (idx + 1) % K);
    return ret;
}

void query_nn(int u, int idx) {
    cmpIdx = idx;
    int next_u = kdTree[u].ls, next_v = kdTree[u].rs;
    if (!(o < kdTree[u].coordinate)) swap(next_u, next_v);
    if (next_u) query_nn(next_u, (idx + 1) % K);

    /* 回溯 */
    push(kdTree[u].coordinate);
    int d = o.d[idx] - kdTree[u].coordinate.d[idx];
    if (next_v && calc_distance(Q.top(), o) >= d * d)
        query_nn(next_v, (idx + 1) % K);
}

int main() {
    while (scanf("%d %d", &n, &K) != EOF) {
        for (int i=0; i<n; i++) 
            for (int j=0; j<K; j++) scanf("%d", &point[i].d[j]);
        nodeCnt = 0;
        build_kdTree(0, n, 0);

        int t;
        scanf("%d", &t);
        while (t--) {
            for (int i=0; i<K; i++) scanf("%d", &o.d[i]);
            scanf("%d", &m);
            query_nn(0, 0);
            printf("the closest %d points are:\n", m);
            while (!Q.empty()) {
                S.push(Q.top());
                Q.pop();
            }
            while (!S.empty()) {
                for (int i=0; i<K; i++) 
                    printf(i < K-1 ? "%d " : "%d\n", S.top().d[i]);
                S.pop();
            }
        }
    }
    return 0;
}

相关文章

  • KD树维护平面点集求近邻

    一道KD树模板题:HDU4347 The Closest M Points。 AC代码:

  • k 近邻法

    k 近邻法 k 近邻算法 k 近邻模型 k 近邻法的实现:kd 树 搜索 kd 树 k 近邻模型实现 k 近邻模型...

  • k近邻&kd树

    1、k近邻 k近邻算法是懒惰学习的代表算法。之所以说k近邻懒惰,是因为它没有显示的训练过程。它的思路很简单,手头有...

  • KNN的实现:kd树(python)

    在寻找输入样本的k个近邻的时候,若进行线性扫描,对于大数据集来说耗时太久,为了加快搜索速度,提出了用kd树实现k个...

  • k近邻

    kd树搜索怎么从最近邻扩展到k近邻 设计一个最小堆(或优先队列),堆大小限制为k,先搜到近似最近邻点u,这个过程中...

  • 机器学习算法—KNN(K近邻)3

    kd树 k近邻算法最简单的实现方式线性扫描 linear scan。需要计算每个输入实例和每个训练实例之间的距离;...

  • KNN算法-4-算法优化-KD树

    KD树 KNN算法的重要步骤是对所有的实例点进行快速k近邻搜索。如果采用线性扫描(linear scan),要计算...

  • KNN近邻算法总结

    目录 一、KNN近邻算法思想 二、KNN模型三大要素 三、KNN算法实现步骤 四、KNN算法的KD树实现 五、总结...

  • KD 树上的 KNN 算法

    kd树knn算法 给定kd树,求距离p点最近的k个样本。零、L为有k个空位的列表(一)、根据p的坐标值和每个节点的...

  • BAT机器学习面试1000题系列(第21~30题)

    21.KNN中的K如何选取的?关于什么是KNN,可以查看此文:《从K近邻算法、距离度量谈到KD树、SIFT+BBF...

网友评论

      本文标题:KD树维护平面点集求近邻

      本文链接:https://www.haomeiwen.com/subject/pdlqlctx.html