Welcome back. Today, we're gonna take a look at a number of interesting

applications of symbol tables and the binary search tree data structure to

address problems with processing geometric data. So let's take a look at it. The idea

is that we're gonna be talking about geometric objects, not simple keys like

strings and numbers. So here's an example. So say your geometric objects are points

in the plane and you specify a rectangle that's oriented with the

horizontal/vertical axes. And you might wanna ask, which points are inside the

rectangle or how many points are inside the rectangle? Or maybe what you are

processing is rectangles. You have a set of rectangles, and we want to know which

of these rectangles intersect? Or how many rectangles intersections are there? These

are interesting problems that have lots and lots of applications, from

computerated design, to games and movies and also in abstractions such as data

bases and other situations where you might have multiple keys or multiple dimensions.

And it's a very interesting extension of the ideas that we've looked at for symbol

tables for all sorts of familiar applications. And, surprisingly binary

search trees and these associated algorithms that we've looked at are going

to provide very efficient solutions to a number of important problems in this area.

And really have enabled a new developments and new technology in all of these kinds

of applications. So, to get started, we're going to look at a simple problem called

one-dimensional range search. And it really forms the basis for what we're

going to do. It's a little bit of an extension of the ordered symbol table API

that we gave before and we're going to have operations range-search and

range-count. So, a one-dimensional just means we have one key, so we'll insert a

key value pairs before and what we want to do is to be able to search for a key, and

a value associated with it, want to b e able to delete. But then we want these

operations range-search and range-count. So, find all the keys that are between two

given keys, or give how many keys are there between two given keys. So, for this

example at right we have insert a number of keys and, and we're just showing them

in sorted order. But then, you might say, well, how many keys are there that are

between g and k? In this case, there's just two. And then the client might say,

well, what are those keys and you want to be able to return them. And this is a very

common operation, say, in databases. You want to return how many taxpayers have

salaries between one million and ten million and then which ones are they and

so forth. So, range searching is a very important fundamental operation. Now, in

geometric interpretation, we just think that the keys as points on a line. And so,

the key values well, are just specified as points on a line. We might convert the

letters to numbers, or we might, keys might be numbers. And then, what we're

looking for is to find or count the points in a given interval in one dimension. So

how we're going ti implement that? Well this is the basic problem that is very

similar to our symbol table problem. We might consider keeping the things in an

unordered array. Just put them in an array, and then, well, insertion is, is

fast. We just add it to the end of the array. We might have to use resizing to

make the array grow. But this is unattractive because for large numbers of

keys, in order to count the keys that fall within a given range, you have to go

through all the keys and test whether they're in the range or not and to return

them the same way. So take linear time for large number of keys. If you keep the

things in order like in a binary search situation then to insert in order to keep

it in order in an array, you might need to move the larger ones over one pos ition

and so forth or elementary implementation of binary search when we did symbol tables

did this. So, the insertion time might be linear, but then you can use binary

search, to look for the two endpoints, that's only going to take time

proportional to log in. And then from that, you can figure out how many keys

there are or return them all between the index, the lowest one in the range, index

the highest one in the range. So, those elementary implementations are no

acceptable for a large numbers of keys cuz they have the linear time operation. So,

what we really want is to have time proportional to log in. For insert and,

and for counting. For range search, of course, we, we have to touch every key

that we return, so the running time is going to be proportional to the number of

keys that match. But anyway, those are reasonable goals. And they're easy to

achieve. So [cough] so, for example what about one-dimensional range counting?

Well, what we're going to do is just keep the keys in a binary search tree and we

looked at the implementation of the rank function for binary search trees where for

every key, we can compute how many keys are there that are strictly less than that

key. So in this case, the rank of e is two and h is three and so forth. So, in a

binary search tree, those rank numbers go in an increasing order as we do in an

ordered traversal and that's easy to compute. You need to keep that rank tree

as a field, or keep a field which has the size of the tree and it's easy to complete

the rank from that. So how many keys between, say e and s? Well one, two,

three, four, five. It's actually just the difference between the ranks plus one if

the high [cough] entry in the range query is in the table and not +one over. So,

there's the same number of keys between e and s as there are between e and t five.

Between f and t, there's only f our. So, that's a, a really 1d range count is a

very easy computation to perform in, in log time with a binary search tree. The

[cough] number of nodes examined when we do a search is the length of the search

path to low plus the length of the search path to high to [cough] find their ranks

and that's going to be time proportional to log N. [cough]. So and a range search.

Well, we just do a recursive search and to find all the keys between low and high you

look in the left subtree if any of them could fall in the range. You look at the

current node and you look at the right subtree, if any of them could fall in the

range. And it's easy to tell whether any of them could fall in the range by just

checking whether they're range overlaps the root or not. So, if we are looking for

all the keys between f and t then we have to look at both the subtrees of the root

s. But we don't to look at the left subtree of e because all of those are less

than e and therefore are less than f. So, we don't have to have to look there. But

otherwise, it's a simple modification of recursive tree search to find all the keys

and it's easy to see the running time to that is going to be proportional to the

number of keys returned plus log N. So, that's one dimensional range search using

binary search trees.