1 2-D Trees You are given a set of points on the plane –Each point is defined by two coordinates...

33
1 2-D Trees You are given a set of points on the plane Each point is defined by two coordinates (x, y) (5,45) (25,35) (35,40) (50,10) (90,5) (85,15) (80,65) (60,75)

Transcript of 1 2-D Trees You are given a set of points on the plane –Each point is defined by two coordinates...

1

2-D Trees• You are given a set of points on the plane

– Each point is defined by two coordinates (x, y)

(5,45)

(25,35)

(35,40)

(50,10)

(90,5)

(85,15)

(80,65)

(60,75)

2

2-D Trees• The problem is to design a Data Structure

that would store these points and perform the following operations efficiently

– Insert - a point into the set– Delete - an existing point from the set– Point Query – given a point, see if it exists in the

set– Range Query – find all points that fall into a – rectangular region– Nearest Neighbor Query – Find the point that is – closest to a given query

point

3

Flashback: 1-D Search Trees• Recall our 1-D search trees

– BST, AVL, Splay, B-Tree …– The problem there was to manipulate keys that

lay over a single axis (thus the name 1-D tree)

– Our search trees worked by cutting this axis at a key point, thus dividing the keys into 2 sets: (1) those smaller than the key, (2) those bigger than the key

– Here is an example

5 25 35 50 60 80 9085

4

1-D Search Trees – BST Example

5 25 35 50 60 80 90

<50 >50

50

80

>80<80

<5

5

>5

35

<35 >35

60

<60 >60

90

>90<90

>25

25

<25

5

2-D Trees• Extension to 2-D trees uses the same idea

– At one level, cut the plane perpendicular to one axis, at the next level, cut it perpendicular to the other

– Arrival order of the points:– (50,10) (25,35) (80,65) (5,45) (60,75) (35,40) (90,5) (85,15)

(50,65)

(50,10)

(25,35)

(80,65)

(5,45)

(60,75)

(35,40)

(90,5)

(85,15)

(50,65)

6

Example 2-D Tree

(50,10)

(25,35)

(80,65)

(5,45)

(60,75)

(35,40)

(90,5)

(85,15)

(50,10)

(25,35) (80,65)

(5,45) (60,75)

(35,40)

(90,5)

(85,15)

x

y

x

y

y

x

y

x

root

(50,65)

(50,65) y

7

2-D Tree Ops – Point Query// axis: 0 means x-axis, 1 means y-axis

TreeNode *Find(TreeNode *t,

Point p, int axis){

if (t == NULL) return NULL;

if (t->p equals p) return t;

if (axis == 0){

if (p.x < t->p.x)

return Find(t->left, p, 1);

else

return Find(t->right, p, 1); //>=

} else {

if (p.y < t->p.y)

return Find(t->left, p, 0);

else

return Find(t->right, p, 0); //>=

} //end-else

} /* end-Find */

(50,10)

(25,35) (80,65)

(5,45) (60,75)

(35,40)

(90,5)

(85,15)

x

y

x

y

root

struct Point {int x, y;}

struct TreeNode {

Point p;

TreeNode *left, *right;

};

TreeNode *root = NULL;

(50,65)

8

Iterative 2-D Tree Point QueryTreeNode *Find(TreeNode *t, Point p){ int axis = 0; // Initial axis

while (t != NULL){

if (t.p equals p) return t;

if (axis == 0){

if (p.x < t->p.x) t = t->left;

else t = t->right; // >=

} else {

if (p.y < t->p.y) t = t->left;

else t = t->right; // >=

} // end-else

axis = !axis; // change the axis

} // end-while

return NULL;

} /* end-Find */

9

2-D Tree Insert(Point p)• Create a new node “z”

and initialize it with the point to insert• E.g.: Insert (95, 80)

• Then, begin at the root and trace a path down the tree as if we are searching for the node that contains the point

• The new node must be a child of the node where we stop the search

NULL

(95,80)

z

Node “z” to be insertedz->p = (95, 80)

NULL

(50,10)

(25,35) (80,65)

(5,45) (60,75)

(35,40)

(90,5)

(85,15)

x

y

x

y

root

(50,65) (95,80)

After (95,80) is inserted

10

2-D Tree Insert point (95,80)

(50,10)

(25,35) (80,65)

(5,45) (60,75)

(35,40)

(90,5)

(85,15)

x

y

x

y

root

(50,65)

(50,10)

(25,35)

(80,65)

(5,45)

(60,75)

(35,40)

(90,5)

(85,15)

(50,65)

(95,80)

(95,80)

root

11

2-D Tree Ops – Insertvoid Insert(TreeNode *t, Point p){

int axis = 0; // Initial axis

TreeNode *z = new TreeNode(p);

while (t){

if (t.p equals p){return; /* duplicate point */}

if (axis == 0){

if (p.x < t->p.x){

if (!t->left){t->left = z; return;} else t = t->left;

} else {

if (!t->right){r->right = z; return;} else t = t->right;

} //end-else

} else { /* axis = 1, i.e., y axis */

if (p.y < t->p.y){

if (!t->left){t->left = z; return;} else t = t->left;

} else {

if (!t->right){r->right = z; return;} else t = t->right;

} //end-else } // end-else

axis = !axis; // change the axis

} // end-while

} /* end-Insert */

12

2-D Tree Ops – Recursive Insert// axis: 0 – x axis, 1 – y axis

TreeNode *Insert(TreeNode *t, Point p, int axis){

if (t == NULL) t = new TreeNode(p);

else if (t->p == p) ; //error: duplicate point

else if (axis == 0){

if (p.x < t->p.x) t->left = Insert(t->left, p, 1);

else t->right = Insert(t->right, p, 1);

} else {

if (p.y < t->p.y) t->left = Insert(t->left, p, 0);

else t->right = Insert(t->right, p, 0);

} //end-else

return t;

} //end-Insert

13

2-D Tree Ops – Delete(Point p)

• Delete is a bit trickier. 3 cases exist1. Node to be deleted has

no children (leaf node)– Delete (35,40)

2. Node to be deleted has 1 child– Delete (90,5)

3. Node to be deleted has 2 children– Delete (50,10)

(50,10)

(25,35) (80,65)

(5,45) (60,75)

(35,40)

(90,5)

(85,15)

x

y

x

y (50,65) (95,80)

root

14

Deletion: Case 1 – Deleting a leaf node

Deleting (35,40): Simply remove the node and adjust the pointers

(50,10)

(25,35) (80,65)

(5,45) (60,75)

(35,40)

(90,5)

(85,15)

x

y

x

y (50,65) (95,80)

root

After (35,40) is deleted

(50,10)

(25,35) (80,65)

(5,45) (60,75)(90,5)

(85,15)

x

y

x

(50,65) (95,80)

root

15

Deletion: Case 2 – A node with one child

Deleting (90,5): “Splice out” the nodeby making a link between

its child and its parent

(50,10)

(25,35) (80,65)

(5,45) (60,75)

(35,40)

(90,5)

(85,15)

x

y

x

y (50,65) (95,80)

root

(50,10)

(25,35) (80,65)

(5,45) (60,75)

(35,40)

(85,15)

x

y

x

y (50,65) (95,80)

root

Is this correct?

NO!

16

Deletion: Case 3 – Node with 2 children

Deleting (50,10): Find the point with the minimum “x” coordinate in the

right subtree, copy its contentsto the deleted node. Then recursively

delete the replacement node

(50,10)

(25,35) (80,65)

(5,45) (60,75)

(35,40)

(90,5)

(85,15)

x

y

x

y (50,65) (95,80)

root(50,65)

(25,35) (80,65)

(5,45) (60,75)

(35,40)

(90,5)

(85,15)

x

y

x

y (95,80)

root

(50,65)

Now recursively delete the replacement node

(50,65)

17

Deletion - Summary• Leaf node – just delete• Internal node (1 or 2 children)

– Find the node with the “minimum” value along the cutting dimension (x or y) in the right subtree. Then recursively delete the replacement node

18

Deletion – Summary (cont)• What if the right subtree is empty?

– Happens if the internal node has 1 left child only

– We can find the node with the “maximum” value along the cutting dimension in the left subtree?

– But this does not work. Recall that we maintain the invariant that points whose coordinates are equal to the cutting axis are stored in the RIGHT subtree.

– If we select the replacement point to be the point with the maximum coordinate from the left subtree, and if there are other points with the same coordinate in this subtree, then we will have violated our invariant!

19

Deletion – Summary (cont)• How do we delete a node with 1 left child

then?– The idea is to find the “minimum” point in the

left subtree, copy it to the deleted node

– Then, move the left subtree over to the right so that it becomes the right child of the deleted node.

– The left child is then set to NULL

20

Deletion Example

(35,60)

(20,45) (60,80)

(90,60)

(80,40)

(50,30)

x

y

root

(10,35)

(20,20)

x

y

(70,20)

(60,10)

x

yDelete

(35,60)

Find replacement:

(50,30)

(50,30)

(20,45) (60,80)

(90,60)

(80,40)

(50,30)

x

y

root

(10,35)

(20,20)

x

y

(70,20)

(60,10)

x

y

Now, recursively delete the replacement node:

(50,30)

Copy data inside the replacement node (50,30) to the deleted node

21

Deletion Example (cont)

(50,30)

(20,45) (60,80)

(90,60)

(80,40)

(50,30)

x

y

root

(10,35)

(20,20)

x

y

(70,20)

(60,10)

x

y

Delete (50,30)

No right child

Find the minimum in the

left subtree: (60, 10)

(50,30)

(20,45) (60,80)

(90,60)

(80,40)

(60,10)

x

y

root

(10,35)

(20,20)

x

y

(70,20)x

(60,10)y

Copy data inside the replacement node (60,10) to the deleted node, and move the left subtree over to

the rightNow, recursively delete the replacement node:

(60,10)

22

FindMin// Returns the point having the minimum value along

// “minAxis” in the tree pointed to by “t”

Point *findMin(TreeNode *t, int minAxis, int axis){

if (t == NULL) return NULL;

else if (minAxis == axis){

if (t->left == NULL) return &t->p;

else return findMin(t->left, minAxis, !axis);

} else {

TreeNode *p1 = findMin(t->left, minAxis, !axis);

TreeNode *p2 = findMin(t->right, minAxis, !axis);

return minimum(&t->p, p1, p2, minAxis);

} //end-else

} //end-findMin

23

FindMin(t, minaxis = 0, axis = 1);

(55,40)

(45,20)(35,75)

(70,60)(10,65)

(20,50)

y

x

(30,25)

(15,10)

y

x (25,85)

t

(60,30)

(25,15)

(70,15) (60,10)

24

2-D Tree Ops - Delete// Deletes point “p” from the tree pointed to by t

TreeNode *Delete(TreeNode *t, Point p, int axis){

if (t == NULL) ; // error deleting nonexistent point

else if (p equals t->p){

if (t->right != NULL){ // take replacement from right

t->p = *(findMin(t->right, axis, !axis);

t->right = Delete(t->right, t->p, !axis);

} else if (t->left != NULL){ // take replacement from left

t->p = *(findMin(t->left, axis, !axis);

t->right = Delete(t->left, p, !axis);

t->left = NULL;

} else

t = NULL;

} else {

... // typical search code here

} //end-else

return t;

} //end-Delete

25

2-D Tree Ops – Nearest Neighbor

• Given a query point “q”, find the point closest to “q”• The distance is measured in Euclidean distances, but

other sorts of distance measures can easily be integrated

2

1

3

5

6

4

7

11

12

9

10

8

13

14

15

16q

26

2-D Tree Ops – Nearest Neighbor

2

1

3

5

6

4

7

11

12

9

10

8

13

14

15

16q

7

6 9

4 1

2 3

5

14 12

118

13 10

x

y

x

y

x

y

x

y

x

15

16Search pathNearest neighbor

• The intuitive approach would be to find the leaf node that contains “q”, and then search it and the neighboring cells for closest neighbor

• The problem is that the nearest neighbor may be very far away in the sense of the tree’s structure

2-D Tree Ops – Nearest Neighbor

2

1

3

5

6

4

7

11

12

9

10

8

13

14

15

16q

7

6 9

4 1

2 3

5

14 12

118

13 10

x

y

x

y

x

y

x

y

x

15

16

Start at the root & maintain the closest point found so far Favor branching towards the subtree where “q” is located. Update closest point if possible 6

1

3

Eliminate braches that are farther away from the closest point found so far.

4

Eliminated

2

Eliminated

5

Update closest point as 5

9

Elim

inat

ed

14

8

13 10

15

12

11

16

Update closest point as 16

28

2-D Tree Ops – Nearest Neighbor// Finds the nearest neighbor of a query point “q”.

// Initially, c->dist = INFINITY, c->p = (undefined, undefined)

void NN(TreeNode *t, int axis, Point q, Rectangle r, Result *c){

if (t == NULL) return;

if (distance(q, r) >= c->dist) return; // no overlap. Eliminate

int dist = distance(q, t->p);

if (dist < c->dist){c->dist = dist; c->p = t->p;}

int qv = q->x; int pv = t->p.x;

if (axis == 1){qv = q->y; pv = t->p.y;}

if (qv < pv){

NN(t->left, !axis, r.trimRight(axis, t->p), c);

NN(t->right, !axis, r.trimLeft(axis, t->p), c);

} else {

NN(t->right, !axis, r.trimLeft(axis, t->p), c);

NN(t->left, !axis, r.trimRight(axis, t->p), c);

} //end-else

} //end-NN

29

• The running time of the nearest neighbor searching can be quite bad in the worst case

– In particular, it is possible to come up with examples where the search visits every node in the tree, and hence the running time is O(n)

– However, the running time can be shown to be much closer to O(logn) where logn is the depth of the tree

2-D Tree Ops – Nearest Neighbor

30

2-D Tree Ops – Range Search

• The problem is to find (count) all points that fall inside a search region (thus the name range search)• In the given example, the range area is the green

rectangle, and points 9, 10 and 12 fall inside this range area

2

1

3

5

6

4

7

11

12

9

10

8

13

14

15

16

31

2-D Tree Ops – Range Search

7

6 9

4 1

2 3

5

14 12

118

13 10

x

y

x

y

x

y

x

y

x

2

1

3

5

6

4

7

11

12

9

10

8

13

14

15

15

16

16inside rangevisited

32

2-D Tree Ops – Range Search// Prints all points that fall inside a range Q

// Q is the range area

// R is the rectangle covered by the tree pointed to by “t”

// Initially R is the whole rectangular area containing ALL points

void rangeSearch(TreeNode *t, int axis, Rectangle Q, Rectangle R){

if (t == NULL) return;

if (Q is disjoint from R) return;

if (Q contains t->p) print t->p;

rangeSearch(t->left, !axis, Q, R.trimRight(axis, t->p));

rangeSearch(t->right, !axis, Q, R.trimLeft(axis, t->p));

} //end-rangeSearch

33

• It is possible to easily extend the 2-D trees to higher dimensions

• In dimension K>=2, the tree is called a K-D tree

– Instead of branching at x or y axis only, we would also branch at other axes (in 3-D, every third level would be branching at the z-axis and so on)

• All 2-D tree operations can easily be extended to K-D trees

K-D Trees