kd-Trees: Data Structure for Efficient Range and Nearest Neighbor Searches, Study notes of Data Structures and Algorithms

Kd-trees is a space partitioning data structure invented in the 1970s by jon bentley. It is a tree-based data structure used for efficient range and nearest neighbor searches in multi-dimensional spaces. Each level of the tree compares against one dimension, and the idea is to have only two children at each node. The tree is constructed by recursively inserting points, and each node contains a point and a 'cutting dimension'. To find a point, we only compare the coordinate from the cutting dimension. The insertion, findmin, and deletion operations in kd-trees, as well as the concept of nearest neighbor searches.

Typology: Study notes

Pre 2010

Uploaded on 07/29/2009

koofers-user-lbm
koofers-user-lbm 🇺🇸

5

(3)

10 documents

1 / 19

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
kd-Trees
CMSC 420
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13

Partial preview of the text

Download kd-Trees: Data Structure for Efficient Range and Nearest Neighbor Searches and more Study notes Data Structures and Algorithms in PDF only on Docsity!

kd-Trees

CMSC 420

kd-Trees

  • Invented in 1970s by Jon Bentley
  • Name originally meant “3d-trees, 4d-trees, etc”

where k was the # of dimensions

  • Now, people say “kd-tree of dimension d”
  • Idea: Each level of the tree compares against 1

dimension.

  • Let’s us have only^ two children^ at each node

(instead of 2

d

kd-tree example

x

y

x

y

insert: (30,40), (5,25), (10,12), (70,70), (50,30), (35,45)

insert(Point x, KDNode t, int cd) { if t == null t = new KDNode(x) else if (x == t.data) // error! duplicate else if (x[cd] < t.data[cd]) t.left = insert(x, t.left, (cd+1) % DIM) else t.right = insert(x, t.right, (cd+1) % DIM) return t }

Insert Code

FindMin

x

y

x

y

(51,75)

(25,40) (10,30) (55,1) (1,10) (70,70) (60,80) (35,90)

FindMin(x-dimension):

(50,50)

FindMin

x

y

x

y

(51,75)

(25,40) (10,30) (55,1) (1,10) (70,70) (60,80) (35,90)

FindMin(y-dimension):

(50,50)

Point findmin(Node T, int dim, int cd): // empty tree if T == NULL : return NULL // T splits on the dimension we’re searching // => only visit left subtree if cd == dim: if t.left == NULL : return t.data else return findmin(T.left, dim, (cd+1)%DIM) // T splits on a different dimension // => have to search both subtrees else : return minimum( findmin(T.left, dim, (cd+1)%DIM), findmin(T.right, dim, (cd+1)%DIM) T.data )

FindMin Code

Delete in kd-trees

Q (^) P

A
Want to delete node A.
Assume cutting
dimension of A is cd
In BST, we’d
findmin (A.right).
Here, we have to
findmin (A.right, cd)
cd
cd B
Everything in Q has
cd-coord < B, and
everything in P has cd-
coord ≥ B

No right subtree --- Solution

- Swap the subtrees of node to

be deleted

- B = find min (T.left) - Replace deleted node by B Q

x^ (x,y)
cd (a,b)
(a,c)
Now, if there is another
point with x=a, it
appears in the right
subtree, where it should

Point delete(Point x, Node T, int cd): if T == NULL : error point not found! next_cd = (cd+1)%DIM // This is the point to delete: if x = T.data: // use min(cd) from right subtree: if t.right != NULL: t.data = findmin(T.right, cd, next_cd) t.right = delete(t.data, t.right, next_cd) // swap subtrees and use min(cd) from new right: else if T.left != NULL: t.data = findmin(T.left, cd, next_cd) t.right = delete(t.data, t.left, next_cd) else t = null // we’re a leaf: just remove // this is not the point, so search for it: else if x[cd] < t.data[cd]: t.left = delete(x, t.left, next_cd) else t.right = delete(x, t.right, next_cd) return t

kd-Trees Nearest Neighbor

  • Idea: traverse the whole tree,^ BUT make two

modifications to prune to search space:

1. Keep variable of closest point C found so far.

Prune subtrees once their bounding boxes say

that they can’t contain any point closer than C

2. Search the subtrees in order that maximizes the

chance for pruning

Nearest Neighbor: Ideas, continued

d

Query
Point Q

T

Bounding box

of subtree

rooted at T

If d > dist(C, Q), then no

point in BB(T) can be

closer to Q than C.

Hence, no reason to search

subtree rooted at T.

Recurse, but start with the subtree “closer” to Q:

First search the subtree that would contain Q if we were

inserting Q below T.

Update the best point so far, if T is better:

if dist(C, Q) > dist(T.data, Q), C := T.data

Nearest Neighbor Facts

  • Might have to search close to the whole tree in the

worst case. [O(n)]

  • In practice, runtime is closer to:

O(

d

  • log n)
  • log n to find cells “near” the query point

d to search around cells in that neighborhood

  • Three important concepts that reoccur in range /

nearest neighbor searching:

storing partial results : keep best so far, and update
pruning : reduce search space by eliminating irrelevant trees.
traversal order : visit the most promising subtree first.