>> OK. Let's talk a little bit about
project that is based on BST iterators. Now despite that, we're going to
do the, we're going [inaudible] with only two-way phrase [inaudible]. So the matter [inaudible] based
iterators we're not going to deal with, but you're going to get a chance to
explore using ADT [inaudible] iterators as well as the threaded [inaudible]. So this document is basically
ready for use. I may have had some details and
clarifications and so on, but I'm, the basic task will not change. You're going to have, your
final [inaudible] objectives are to develop some class templates. One is going to be in order BT
iterator, BT is for [inaudible]. [Inaudible] BT iterator
and thread BT iterator. And this is going to be class ten
points, and you got to use those to implement BST threaded, which,
obviously, means binary circuitry with threaded iterators, BSTADT, which
is [inaudible] with ADT iterators, and red black left lean
[inaudible] with ADT iterators. And this would be a big
project, as I say in here. If you were having to start [inaudible], there's a lot of technical engineering
details that you have to get done and do carefully and correctly,
or things blow up on you. You're hearing the voice
of experience on that. So it's not, you could do all that. We all could do that, but it would
take a month or so, and we don't have that much time to devote to the project, and so what I'm doing is giving you
partials on all of these things, and your task then becomes understand
what is dire and also, of course, understand what you add
to make everything work, and while just understanding
the big picture of how these pieces fit together
is an important part of the task, and you need to be able to do that. So there's two sets, two collection of
classes that you've got to deal with. Virtually iterator classes,
and they're all in this thing called BT2 [inaudible] H.
The 2 is for two-way nodes as opposed to three-way nodes, and you've got an in order BT iterator ten point
threaded and [inaudible]. These type just an abstract
class C as a template parameter, and basically you program 2C to as if
it had a node with the functionalities that we have decided we want,
and then when you plug in any of your [inaudible] classes
in for that, they would work. So that's a way of defining those
three kinds of iterators in a way that will make them be able to be
retargeted without rewriting the code to any [inaudible] classes. Then we're going to have some
binary [inaudible] classes, and it's going to be a BSC base,
and that is going to be kind of an iterator free version
of buyer research tree. It's going to contain a lot of
functionalities that can be inherited without change such as the size,
the number of nodes, and the tree. Being able to find, and we'll go
over a lot of those in a few minutes. So that's a base class, and it
serves mainly the purpose of a place that we can store code, and we'll reuse
it by inheritance instead of having to rewrite a copy of
it into another file. So BSCASDT is clearly
[inaudible] iterators. So it's going to inherit
from the BST base class. The AST thread will also
inherit from a BST base class. And RVLLT underscore ADT, that
class will inherit from BSTADT. So your inheritance diagram
here will look like this. You have base. You have thread. You have ADT, and [inaudible]
of ADT we have the RVLLT. I didn't write all these classes
out, but that's the idea of the base. BST base stores a lot of the
boilerplate BSTADT and DST thread. Each inherit this, but to find
iterators in two ways, and, finally, RVLLT underscore ADT inherits from
BST underscore ADT, and, of course, there's work to do here in redefining
the insert because you've got to insert and maintain all the color
structure for red [inaudible], and you've already had
some experience integrating that with your order
associative array project. So this is going to be, to some
extent, plowing over [inaudible], but also a way of getting a grip on some of these various concepts
and how they can be used. So you're also being given an iterate,
a star on the iterator [inaudible], the BSTADT file, BST thread
plow, the RVLADT file. So those are start offs, and
really they contain a fair portion of the code already written. Obviously, I'm leading
[phonetic] out critical things. I don't want you to have
to experience [inaudible]. And then you've got your test harness
FBST, which can be [inaudible] to three different element types
- ent, string, and capital CHAR - and also three different tree types -
BST, [inaudible] BST, ADT, and RBLTADT. So that with just commenting
and uncommenting as is my habit. That one child expands into
nine different test harnesses. And I just realized that
there's also an MBST. I didn't write that down,
but I need to do that. [Inaudible] it's there for you to get. MBST is, of course, the memory retester
just like we had for [inaudible] and way back the list, and you basically
run that with a contained amount of memory, and if it runs
forever, then you're not leaking, but it also does various technical
tests on the iterators and [inaudible]. So, you know, it test iterators for
if you go forward and then backward, you get, you come back
where you started. You know, little rests, [inaudible]
tests like that on the iterators. So if your iterators are going
astray, that'll detect it. And also there's all [inaudible] of the
FBST's are compiled for you [inaudible]. And while all six of those are here, and three more are compiled [inaudible]
RBLT's, MBST's, and [inaudible] MB, and R, and RVLLT's are, these
are all compiled in that area of 51 for you to be able to say. So what you got to do is create the
[inaudible] versions of the start, the four start files by just, you copy
the star to about 8's and then you begin to edit without 8's until it's done. So the way that works, it's like you'd
expect, and so let's just take a look. [ Background Sounds ] Now, you know, iterators are
not spectacular to demonstrate. All they do is provide a different
way to traverse a structure. So it's not particularly exciting
to see these demonstrations. What I'm going to do is, of
course, it can be exciting if your demonstration goes wild on you,
but I'm certain you'd all enjoy that. So I won't risk it. But we make all of our [inaudible],
and this is going to make 9F tests, 6M tests, and I think two utilities
that generate random [inaudible]. [ Background Sounds ] So those are all the
executables that [inaudible]. That's one, two, three, four, five, six,
seven, eight, nine, ten FS6 and tests and two random object generators. So what I think might be instructive
is just take a look at some of these, some of the class start offs
that I've, you know, given. So I think maybe I'll use the editor. So let's look first at BST base. And, by the way, BST
base is fully functional. I didn't mean [inaudible]. [ Background Sounds and Inaudible ] Yeah. Not [inaudible], too. Well, we'll leave that there. So [inaudible] so I didn't
mean to personalize that. [Inaudible] there. So this your BST base class. [Inaudible] FSU. Notice I'm pre-declaring BST base
in our iterator, level iterator, and in case somebody wanted to, like,
come back later, pre-order iterator, folks are [inaudible], this
should be a BT in there, you know, [inaudible] BT iterator. We're not on the final
[inaudible], but you could. Anyway, so here's the class BST base. Notice as usual that the
second template argument has, second template parameter
has a [inaudible] argument, which is less than. So this all starts off just like most
classes do with a bunch of terminology and definitions, and we're defining in order level [inaudible] types
internally to the base class. That doesn't mean we're
going to implement all those, but we're just define what
those words will mean. OK. This space class is, got a
constructor, a one argument constructor that takes if you've already
got [inaudible] you want to use. If there is a copy constructor, destructor [inaudible] inheritance
environment [inaudible] like a virtual. I don't really think we would
ever [inaudible], you know, one time probably [inaudible]
all this stuff, but if somebody decided they
wanted to, you got to [inaudible]. Assignment operator, and not, instead of again [inaudible] I've
got begin level order. That's just a, that's a function,
and it returns the level or iterator, of course, meaning at the beginning of a
level or reversal, and you got n level r which returns the end of [inaudible]
reversal as a level r iterator. And you've got same thing for begin
[inaudible] and in order to begin for [inaudible] or begin
or end in order. If I just went and erased the
end order here in these four, I would be defining official
iterator class or BST base. I just chose not to do that. So we're officially BS base doesn't have
quote iterators even though it's got [inaudible] iterators. And then finally there's this thing
called begin structural in order, and that will be needed when you have
to go through a tree and look at all of the nodes, even those that are dead. So sometimes when you do structural
stuff in the tree, you have to look at the node, whether it's
considered alive or dead, and so that's what this sort of begin
structural kind of thing is for. My client programs never deal with that. Client program aren't going to be
dealing with the structural stuff. So that's we could probably
have made that private, and it would have been fine, or
protected, and it would have been fine. Somewhere on a derived class
[inaudible], but not anytime program. And we've got insert. Of course, we've decided
[inaudible] remove it's time consuming and hard to program. So we're going to have to erase
and [inaudible], and we're going to have insert, put and
get, erase and clear. We're going to have now those
little commented out things if I [inaudible] just to remind all
of us that in a truly functional set, we're going to need a motion
of iterator and a motion of, and use that to define lower bound,
upper bound, include functions. That's going to come
in our derived classes. But here we've got any
sized number of nodes, high. We've got traverse. It refers to [inaudible], the display
function, but it is, you know, the special class print node and
the special recursive reversal. We've got dot methods. We've got a check VHC, which is going
to go through and check the properties on the buyer research
tree, and prototyping but not implementing in
this file a check RBLT. I'm prototyping it in the base
class because it's just simpler because you've got to really
get in and look at, you know, you've got to get your hands on
the private data of the base class, and it's just simpler to clear it here,
even if you're not going to implement until you get down to a [inaudible]. And here's something I actually needed
myself and, therefore, put in here. I call it snapshot. Let me just emphasize that all of
this is development assistant self. That, oh, I'm sorry, even this. So the three dots, the
checks, and the snapshots. Those are things developers use
to make sure everything's right, and then you would even take up,
you would probably just take those out with the interface when you delivered this thing
as an implementation set. Snapshot, what snapshot does is write
to a file a picture of the tree, and I'll just tell you
how that has to work. If you want a file of the data and the
tree that puts the data in the order such that if you read it and insert it, you get back exactly the same binary
tree structure that you had before. Of course, you'd get back
the same set, but I'm talking about the same binary tree structure. Now that's a little, takes a little
thought, and what you have to do is, and what you have to do is use something
besides an in order reversal to do that. [Inaudible] traversal, write it down in
order, and if you insert it in order, well, if it's a binary circuit, inserting it in order will just give
you a tree with a root and a right tail and a right tail and a
right tail and right tail, just a string of right
children looking like a list. So what you want to do is use a level
or a traversal, which would be the root and then the left and right child root,
and then the left, right, left, right, those and so on going down the
levels, but if you come back and insert those using just ordinary
binary tree [inaudible] the insert, you'll get back exactly the
tree structure that you saved. And the reason you care about something
like that is for debugging purposes, and I needed that to debug
the threaded iterator. I was a having a little, couple
issues with threaded iterator. So I would run the memory test, and
after about five minutes, and, you know, with a couple thousand nodes in the
tree, this thing would give me an error on the, on checking the
integrity of those iterators. And so look at what I did
is the take the snapshot. So if you ever detect a lack
of integrity in the iterator, then immediately stop
running the memory test, and just a snapshot of a tree to a file. And so then you can come back and look
at that tree with one of your f tests, and try to figure out, well, what
in the world is going on here because you've got a picture of the tree
that made it a particular failure, how. So that turned out to be
real handy [inaudible]. We've got the flag 0 dead, red, left,
right, and threads, convenience defined to be left red set and the right
red set, which [inaudible]. Protected, we've got [inaudible]. We're going to make the various
iterator classes friendly. I've got node. So this is the node class
that we've been talking about. Because all the node functionality
is red, is black, set red, set black, set [inaudible], has left
[inaudible] on set right thread, set right child, and so on. All those things there. The dump functions are all defined. So all these down here are [inaudible],
and don't need to be redefined. And, by the way, the
recursive functions get. So there's a binary circuitry tree. This thing's wrong. [Inaudible] So there are a lot
of code captured in BST base or that get [inaudible]
used, and that's ready to go. I could, there's a copy of that
already in the course library. So you're getting a copy of that,
which you don't really need, but you probably would like that for
reference because it's where a lot of the function [inaudible]. So let's look at next. [ Background Sounds ] This is your start file for
BT2 header, and this starts out just like the complete one. Again, you pre-declare the
classes you want to talk about, and here's your class level or iterator. Notice that there was a couple
of interesting little tricks here that I'm going to show you. Remember, this has just got an
abstract class c for [inaudible]. Of course, c must have
a value type defined where you're going to crash [inaudible]. It's got to have a node type
defined [inaudible] crash here. We'll define our iterators, we
define content earlier to be the same as iterator just in case
somebody decides they want to use the word [inaudible]. Let me remind you that iterators of these [inaudible]
classes are all [inaudible]. So whether you call it an
iterator or a cost iterator, its behavior is [inaudible]. Now here's one trick for a and c. OK. So that means when I put in,
let's say, BSTADT right there, BSTADT is a friend of this class. So it can go straight in there and deal with that Q directly
if it want, needs to. But [inaudible]. So client programs can only use the
public interface of the iterator. Anyway, so notice that there's
one data item in this iterator, which is a Q [inaudible] to nodes. This should remind you a lot of the
[inaudible] for you got Q pointers to sells as your controller. Some of this is done in line here. So there's your constructor. I explicitly call [inaudible]
Q. According to the iso [phonetic] standard, that one should not be
necessary, but I do it anyway. Kind of helps me remember, you
know, what's really happening when you initialize one of these things, and gives it the antibody
destructor calls Q to clear again. That's probably unnecessary because the
Q destructors, I know it's unnecessary. The Q destructor should
be working, but it just, I like to sometimes know
what's going on. Call me a busybody if you want. Anyway, so copy destructor,
assignment operator. Let's see what else we got. We've got valid. It's handy to know whether or not it's
going to be legal, but look at the top of the queue, and that's
what valuable means. So that means the queue's not empty. We've got equals, not
equals being referenced. Prefix increment and post-fix increment. Notice there's no decrement here. So level of an [inaudible] is going to be a follower [inaudible]
not by direction. You can't back on all these [inaudible]. In private, we have the [inaudible]
and the increment function. Now those are private. So they're not open to clients,
but because any free class that uses them is a friend, a
free class itself will be able to use these functions. Kind of little tricks. So here it is, your admit,
and that's where you run into your first required implementation. So you've got to figure out how to
implement [inaudible] and increment. You won't have any trouble figuring
that out, and while we talked about early [inaudible] in the slides
and your current experience with, you know, how you did in
the wrap, for example. So it's basically you've got the queue,
you look at the front of the queue. If the front, [inaudible]. That's what increment does. And then I've implemented
an operator plus plus here like I said I would in the slide. Do increment while the queue is not
empty and the form of the queue is dead. So that's says increment once,
and then keep doing it more until you come across a live node. [ Background Sounds ] Now this is in order. It starts off almost like Q.
Same sort of type [inaudible]. That you could define a stack with
the default, and you might want to change this to the default or
change it to the deck base stack. Because deck, the advantage of a deck
base stack over a vector base stack is that deck has much stronger
support for mishandled operations, and you get error messages whereas in a
vector, there's a lot less protection, and you sometimes just got to crash
if things are not going right. But, of course, the vector is faster. So once you've got to debug, you may move onto the vector
implementation and stack. Anyway, there's an FSU stack
which is called STK underscore, and it's first class [inaudible] more
what I've been calling a proper type. It's got the big four,
constructor, restructor, [inaudible] constructor,
and assignment operator. Got valid. In this case, it's returning, well,
the stack has not [inaudible]. Got equality, not equality, dereference,
prefix increment, post-fix increment, and now we have also prefix
decrement and post-fix decrement. So we'll stack, so this kind of
iterator can go forward and backward. It's a bi-directional iterator. And the prime, it looks just like
the [inaudible] from the previous. We've got an [inaudible], an r and
increment, [inaudible], decrement. We've got one little [inaudible]
thing, and that's our S event. S is for structural. Again, the [inaudible]
function itself is going to skip to the first live node [inaudible]
structural, and it will just go to the first node, even if it's dead. So to think where you need
to look at the structure, s and [inaudible] would be it. So if you wanted to do a structural
traversal of one of these binary trees, you would instead of using
a normal traversal syntax, you would do something like this. You would do the IBR, I'm sorry. [Inaudible] you do I dot [inaudible]
by what's say the root of you tree, and then your traversal would be for,
it's, [inaudible] already initialized. I not equal to n. Instead of plus
plus sign, you would put increment. And so that will go through,
remember, increment just goes to the next structural node. Operator plus plus goes to
next live structural node. And so this increment
goes to the next node in the actual physical tree
structure where, and this initializes so that first node and the actual
physical tree structure ignoring whether or not it's dead. So just handy little things. Now those are, of course, kind
of technique is only available to the implementation of the
binary tree that you're working on. It's not available to client programs. Client programs only, they can initialize an iterator
only with the begin function. It's a member of a class, and
they can go to the next node only with the plus plus function. They can't use these [inaudible] things. Those are private, and they can't
use the [inaudible] and decrement. Those are private. Only the friends of this class can
do that, and those would be the trees that are using these kind of iterators. [ Background Sounds ] So let's look at structural
[inaudible] here. That's a little bit instructive. So you get a node, typically
that might be a root of a tree. If the, if that root, if that node
is null, then you just go home. Otherwise, clear stack push in on
the stack, and while n is not null and it has a left child, go to that
left child, and push in on the stack. And I want to just draw a
picture of what's going on here. What you're doing is creating a stack
that is like, it's like a lifeline if you, form the root down to the
current location of that iterator. So let's say there's the root. [ Background Sounds ] What, if we were to emit
from here, remember, this is in order, that
will go down to here. So there would be, that would be,
I'm going to put a subscript 1 there. That would be the first place we will
get to in that structural iteration, and we will have our stack would
represent this path down to 1. So the stack is telling us
what that little path is. And then to get to the next one,
we can't go down any further. So we have to go up to the right here,
and so the next one will be that node. So that would be 2. And we get there by popping the stack. So that's the new lifeline is just
the stack with only one thing in it. And then the next number 3 will be,
you go to the right and slide left, so that would be here and here. That will take you to 3, and so
my lifeline from the root is now that red path all the way down. So the stack always has the kind
of lifeline back up to the root, but you need to be able
to climb the tree. You can think of it as like
a climbing rope or something. So you kind of rappel
down where you need to be, and you use the rope to climb back up. You need that rope because
there's no parent pointers. So that's the function of the stack
in this process, and it keeps track of where you are by keeping this little
red [inaudible] and stack all the time. And, you know, as the stack
size grows and tracks. So the stack is using some memory, and
people might say, oh, you're using a lot of memory for your iterators. Well, the alternative was if you
recalled to put parent pointers in in every node in the tree. Well, that uses up a lot more memory
because you've got n extra pointers in there that are direct required
whereas the most extra pointers you'd be storing the stack is a
root to know the path which in a good typical
case there's only about the logarithm of n worth of stuff. Though the stack sizes are logarithmic
compared to the size of the tree itself, and so this is not all that wasteful. And the cool thing is they work
[inaudible] external to any of the internal tree structure. So that it will be just as
easy to find these things for red black left leaning trees
as it is for binary searches. [ Background Sounds ] So the [inaudible]. So I, that's the structural [inaudible],
and I kind of left [inaudible] as you can imagine here by commenting
out the part that you don't [inaudible] when it's a structural admit, and
you do when it's a regular admit. So copy that, [inaudible]
while we [inaudible]. R admit, I'm going to
let you figure out. It's the left-handed
version of an [inaudible]. [ Background Sounds ] Increment, you've got, and, you
know, that's pretty complicated, but you want to be able
to understand that. And one way you can test here
understanding it of it is by programming decrement, which is
the left-handed version of increment. So every time you did it to the
right or you do for the left, and everything you did to the
left or you did to the right. Fortunately, up stays up. Anyway, I think that's
the last [inaudible], I think everything else, there, yeah. So everything else and [inaudible]
iterator was implemented already. So you've got to do the
admit and the, I'm sorry, I guess that's [inaudible]
and decrement. And, finally, we get the thread, and
thread is the most efficient of all, but it's really tough
to program, and thread, instead of maintaining
this little lifeline back to the root in a threaded tree. [ Background Sounds ] So there's a tree, and a threaded
tree, let's say, well, to initialize, of course, you start at the
root and go down the left side. So that would be your first
location, and you get there by going down normal left child pointers. But you, when you get
down to the bottom, what you discover is not these are
null but because this is threaded, what you have is a couple
things that are there, but they're threads not children. And so this, when you hear it detects
that that right thing is a thread, and what that thread has got point
to is where you go from here, and in this case, it's
back to its parent. So when you get to parent,
parent has a rear right child on either the left side,
and you get down to here. So I got to keep my colors
straight here. So that's first place to visit,
that's the second place to visit. Left and right side. There's a third place to visit. This right child doesn't exist. There's a thread [inaudible]. So it points to where you
would go next, which is here. This right child is thread, and it points to where you
would go next, which is here. This right child is real. Been keeping track of the numbers. That's 3, 4, 5. This right child is real, 6. You do a left side, but there
isn't any place to go, right. So that's where you stop, 6. Six, right child is a friend
that points to where you next. Well, where you go next is here. [ Background Sounds ] So that was 7 in my iteration. And 7 I go to here, and
I work on the left side. So they all turn into 8. Eight's right child has to be a
thread going back to its parent. So that's a 9. Nine's right child exist. You do a left side that
takes you to here, 10. Ten's right child must be a thread
that's going to [inaudible] the parent. This guy's right child
must be, doesn't exist. So it's a thread that's going
to take you off the tree. So it's actually not being a
thread when it's a null corner, indicating the end of the iteration. And then that [inaudible] the
what would normally be null or right children to, as threads. If you're doing decrement, you would be
using what would normally be the null or left children to point where you
would go in the other direction. And that's now threaded tree,
and that's probably efficient. First of all, these upward
things are just leaps. So from here to here is just a
one move from 6 to 7, for example, rather than having to pop a stack up to
get there, number one, and, number two, the iterator is just a pointer to a node
rather than a stacker [inaudible], and, finally, the tree itself, you're
just making use of the pointers that would otherwise be null and the tree structures here aren't
adding any extra memory that you've got to carry along in the tree. Very efficient. And so that's, you're going to do
that for binary tree [inaudible]. Now this is tough. This requires you to be careful through
set of threads in your binary tree when you're doing a thing
like [inaudible]. It has to be done carefully, but it's
explained in the notes how to do it, and there's enough of the things
are intimated for you to kind of see how the rest of them will go,
but where it will get really difficult, and quite frankly I tried several
times and couldn't even figure out how to do it, is doing it for a
left [inaudible] red black left leaning trees. Now I know how you would really do it. The way you would really
do it is you would change that red black left leaning insert,
for example, to, you'd change it from recursive to [inaudible]. It would be a complicated iterative
algorithm to do that insert, but that's the way you would do it,
and then once you got it [inaudible], then you set threads just
like you do for binary search. But the advantage of left [inaudible]
tree technology for us is it's, by far and away, the simplest
self-balancing tree that's been invented, and it's quite a
recent invention as you recall from the introductory nodes. [Inaudible] check unbalanced trees. And so we couldn't go down that road,
and we would if we were really going to be delivering a, something from
[inaudible], but we're just going to use ADT based iterators and
create iterators for [inaudible]. Now we shouldn't be too
disappointed by that. Those are very handy
iterators, and, for example, in a language like Java, that's it. I mean, the iterator are going to
be stack implemented, not threaded. And so, and, by the way, in
the standard template library, your set is implemented as red black
tree, but it, the classic version of red black tree, which was invented
25 years ago, not just a few years ago, in the class [inaudible] red black
tree, it has the same efficiencies as left land red black tree, but it's a
significantly more complicated algorithm whether you do it recursively
or not recursively, and it's a little bit harder to
understand how all that stuff works, but once you, but, again,
it's just do the heavy work, implement where red black
tree is iteratively, and then you can do thread iterators. Now what you will find in the
standard template library is that set is implemented in
these classic red black trees. Set copy is disabled because there was
not, people couldn't figure out how to make, how to efficiently copy a tree
and copy the threading of the tree. Because those are just pointers
to other places in the tree, and it's not clear how to make those
[inaudible] analogs go over in the copy. How do you get your hands on the place
where that pointer should be defined. I actually came up with
a way of doing that, and so our threaded binary search tree
class is actually a full-fledged class with copy constructor and [inaudible]
operator, and the way I figured out how to do that is by [inaudible]
and call set all thread heads that you have to [inaudible]. Now what set all thread does is use
an [inaudible] iterator to iterate through the new copy of the tree, and just simply send the
threads to what [inaudible]. So when you do an [inaudible] iterator
to a stack through one of these trees, whenever you get to a node, if that
[inaudible] the left child is a child who did nothing, but if it's a null,
then you make a point to the place where you came from in the iteration. And when you get to null right
child, you make it point to the place where you're going next [inaudible]. So by using an [inaudible]
iteration one time through tree, an in order iterator I should say,
using, which uses stack controller, you can go through the
tree, set all the threads, that's just one time during the copy
process, and then from there on, you've got threaded iterations
in the new tree. So it makes the copy a
little more expensive. Still [inaudible] but it's
more end than it used to be. The constant is a lot bigger,
but once the copy's made, you've got to thread it,
tree, got all the way up to [inaudible] thread iterations. And you can do that same thing. A red black tree is what's [inaudible]. So we could go in and use that
to implement the copy aspects of red black trees and STL to
constant [inaudible] saved. So what I want you to do is learn
from this how the code fits together. You've got all these classes. Some are inherited from others. You've got these other independent
classes that are iterator classes. You've got two different, we've got
three different kinds of iterators here. We've got threaded iterators, we've
got in order stack based iterators, and we've got level of
order of Q based iterators. How those things work and so on. You've got to implement some of the
key pieces of each one of those, but more generally, I want you to kind
of step back, take an engineer's look at the way all that stuff is designed so
that you know how global understanding in [inaudible] as well as
details about how it fits to go. So that's what you need
to get out of project two.