创建一个逻辑插入和可视化的KDTree

时间:2014-01-25 08:14:46

标签: java data-structures kdtree recursive-datastructures

所以我的任务是编写一个具有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

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

然后我们到达第4,5,6和4点。 7.第4点是垂直的,因为它的深度是均匀的,第5点也是如此。它的x点小于点1,因此它向左移动,其x点大于点2,因此它向右移动,成为点3s'右子,它应该使其深度均匀,因此是垂直的。正确的子树也存在同样的问题。

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

1 个答案:

答案 0 :(得分:0)

  

然后我们到达第4,5,6和4点。 7.第4点是垂直的,因为它   深度是均匀的,第5点也应该是。它的x点小于   点1,所以它向左移动,其x点大于点2,   所以它走向正确,成为第3点'正确的孩子,应该   使其深度均匀,垂直。同样的问题是对的   子树。

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

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