|
|||||||||||||||||||||||||||
|
Due 11:59 PM, Sunday April 22, 2001 In this lab we will explore how we can make a binary tree appear as a linear entity. This process is called "iterating". Iterators are different than a lot of what we have been doing since the "order" of the elements in a binary tree extrinsic to the tree, that is, it is dependent on an external insertion algorithm to determine how new elements are added the tree. Iterators are used when the elements of a tree need to be processed in a very specific order, not necessarily directly related to their position in the tree. An example is the very important usage of binary trees in compiler design where the code written in a particular programming language is parsed into an "abstract syntax tree". This abstact syntax tree is an equivalent representation of the code where the parenthesis have been eliminated and variables stored in leaf nodes, while the interior nodes contain the operators the user specified for use on those variables. In this lab we will use the BSTInsertAlgo and other Binary Search Tree capabilities developed in class to provide a consistent way of inserting and removing nodes from the tree
Different Types of Iterators (non-exhaustive list)Note: In all the iterations described below, "left" can be interchanged with "right", so the iteration progresses in the opposite horizontal direction across the tree, with no loss of generality. The following descriptions will give iteration results for the following two examples: An example of a binary tree:
An example of an abstract syntax tree with operators and variables:
Depth first/Pre-fix order :
Breadth first
In order/in-fix order :
Post-fix order :
The Use of a Stack and Queues as a Pending-State Storage DevicesRecursion is a wonderful thing, but it has one serious drawback: it can't be stopped in the middle and restarted some arbitrary time later (single threading assumed here). Contrast this to a for-loop that could be stopped in the middle, save the main counter value, and then be restarted at the saved counter value at any time later. The problem is all those pending operations in a recursive process. The problem manifests itself here because we'd like to do a recursive process to iterate through the list, but unless we want to pre-process the entire tree by saving every element in its proper order in a list, we cannot restart the recursion at the place it left off every time nextElement() is called. We can cheat a little here and not try to save the entire state of the recursion. We need only find a way of storing all the pending nodes that we have recurred through and are going to return to and continue their processing at a later time. If we were retrieving data grom the leaf nodes before the parents, this storage mechanism would save each node as we recurred down to the next level, seeking the leaf node. The leaf node's data would be returned with the subsquent nextElement() call. Having done that, the iterator would pull the nearest parent node from the storage mechanism as the next node to process. This is "First-In, Last-Out" (FILO) behavior and maps perfectly over to a Stack implementation. On the other hand, if the parents are all retrieved before the children ever are, a "First-In, First-Out" behavior, then a Queue is more warranted. Note that this method is far superior to pre-processing the whole tree because only a temporary storage of size O(log(n)) is needed instead of the O(n) size needed if the tree were completely pre-processed. So, all we have to do is to figure out clever ways to store nodes of the tree in a Stack or Queue so that we can retrieve them when they are needed. Sure, no problem....uh, huh.....
Doing It OrderComplete this lab in this order:
Adding MenuBars in JBuilder
Tip: Clearing the JPanelAll containers have a "removeAll()" method that removes all the sub-Components they contain.
|
||||||||||||||||||||||||||