【问题标题】:Creating a KDTree that inserts and visualizes logically创建一个逻辑插入和可视化的 KDTree
【发布时间】:2014-02-16 08:50:56
【问题描述】:

因此,我的任务是构建具有 Point2D 类型节点的 KdTree。首先从 insert 方法开始,以确保节点被 x 轴相应地放置,然后构造与它一致的 draw() 方法。

我已经做到了,并完成了其他一些方法,而我并没有从试图弄清​​楚前两种方法中抽出头发,但这是我的问题..

我的构造适用于每个测试,视觉和性能方面,但我仍然认为它不正确。

package algs32.kdtree;
import algs12.Point2D;
import algs13.Queue;
import stdlib.*;

public class KdTree {

    private static class KNode {
        private KNode left, right;
        private boolean vertical;
        private Point2D key;

        public KNode(final Point2D key, final boolean v) {
            this.key = key;
            vertical = v;
        }
    }
    private static final RectHV BOUNDRY = new RectHV(0, 0, 1, 1);
    private KNode root;
    private int size;

    public KdTree() {}

    public int size() { return size; }

    public boolean isEmpty() { return size == 0; }


    public void insert(Point2D p) { root = insert(root, p, true); }

    private KNode insert(KNode node, final Point2D p, final boolean vertical) {
        if (p == null) { throw new IllegalArgumentException(); }
        if (node == null) {
            size++;
            node = new KNode(p, vertical);
            return node;
        }
        if (p.equals(node.key)) { return node; }
        if (node.vertical && p.x() < node.key.x() || !node.vertical && p.y() < node.key.y()) {
            node.left = insert(node.left, p, !node.vertical);
        }
        else {
            node.right = insert(node.right, p, !node.vertical);
        }
        return node;
    }

    public void draw() { draw (root, BOUNDRY); }

    private void draw (KNode node, RectHV area) {
        if (node==null) return;

        StdDraw.setPenColor(StdDraw.BLACK);
        StdDraw.setPenRadius(.007);
        node.key.draw();

        StdDraw.setPenRadius(.002);
        if (node.vertical) {
            StdDraw.setPenColor(StdDraw.RED);
            StdDraw.line(node.key.x(), area.ymin(), node.key.x(), area.ymax());
        } else {
            StdDraw.setPenColor(StdDraw.BLUE);
            StdDraw.line(area.xmin(), node.key.y(), area.xmax(), node.key.y());
        }
        draw(node.left, LR(area, node));
        draw(node.right, RR(area, node));
    }

    private static RectHV LR(RectHV area, KNode node) {
        if (node.vertical) {
            RectHV newarea = new RectHV(area.xmin(), area.ymin(), node.key.x(), area.ymax());
            return area;
        } else {// BR for horizontal division
            RectHV newarea = new RectHV(area.xmin(), area.ymin(), area.xmax(), node.key.y());
            return area;
        }
    }

    private static RectHV RR(RectHV area, KNode node) {
        if (node.vertical) {
            RectHV newarea = new RectHV(node.key.x(), area.ymin(), area.xmax(), area.ymax());
            return newarea;
        } else {// TR for horizontal division
            RectHV newarea = new RectHV(area.xmin(), node.key.y(), area.xmax(), area.ymax());
            return area;
        }
    }

Graph

这是我的代码的可视化。点号是插入的顺序。 如您所见,点 1 是根,(首先插入),点 2 向左移动,因为它的 x 坐标较小,点 3 向右等。

然后我们到达点 4、5、6 和 7。点 4 是垂直的,因为它的深度是均匀的,点 5 也应该是垂直的。它的x点小于点1,所以它向左,它的x点大于点2,所以它向右,成为点3s的右孩子,应该使它的深度均匀,从而垂直。右子树也有同样的问题。

非常欢迎任何额外的解释。

【问题讨论】:

    标签: java data-structures kdtree recursive-datastructures


    【解决方案1】:

    然后我们到达点 4、5、6 和 7。点 4 是垂直的,因为它 深度是均匀的,第5点也应该是。它的 x 点小于 点 1,所以它向左走,它的 x 点比点 2 大, 所以它向右,成为点 3s 的右孩子,应该 使其深度均匀,从而垂直。右边也有同样的问题 子树。

    这是不正确的。一旦你走下树的一根树枝,你就会呆在那里。所以点 1 位于根部,有孩子 2 和 3。2 有孩子 4,4 有孩子 5。因此 5 应该是水平的,因为它是 4 的孩子,它是 2 的孩子,它是 2 的孩子1. 维基百科对 kd-trees 有很好的解释:http://en.wikipedia.org/wiki/K-d_tree

    总而言之,由于点 5 在 1 的左侧,因此它进入了该分支。由于它低于 2,因此它采用该分支。因为它在 4 的右边,所以它需要那个分支。

    【讨论】:

      猜你喜欢
      • 2020-07-05
      • 1970-01-01
      • 2020-12-07
      • 1970-01-01
      • 1970-01-01
      • 2021-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多