teaching binary tree algorithms through visual...

14
Teaching Binary Tree Algorithms through Visual Programming Amir Michail Abstract In this paper, we show how visual programming can be used to teach binary tree algorithms. In our approach, the student implements a binary tree algorithm by manip- ulating abstract tree fragments (not necessarily just single nodes) in a visual way. This work contributes to visual programming research by combining elements of anima- tion, programming, and proof to produce an educational visual programming tool. In addition, we introduce Op- sis, a system we built to demonstrate the ideas in this paper. (Opsis is a Java applet and can be accessed at http://www.cs.washington.edu/homes/amir/Opsis.html.) We describe our experience with using Opsis in a data struc- tures and algorithms course at the University of Washing- ton. Finally, we make the claim that visual programming is an ideal way to teach data structure algorithms. 1 Introduction The idea of using computers to teach algorithms is not new; computer animations are used to illustrate many al- gorithms. Although one might gain insight from watching an algorithm animation, it is often the case, as with any pass- ive activity, that important details are glossed over or missed altogether. Indeed, the student may not really understand the algorithm but merely have a pretense of having done so. Empirical evidence suggests that students learn better through active rather than passive activities.[9] A more active method is to have the student implement the algorithm in some textual programming language. In this way, the student must understand the details of the al- gorithm in order to implement it correctly. However, al- though the student may now understand how the algorithm works, this does not mean the student understands why it works. Moreover, the student often has to go through the drudgery of low-level details, such as pointer manipulation, that are not crucial to understanding the algorithm. Worse yet, the algorithm may naturally require the formulation of mental pictures not readily expressible in code — the stu- dent must constantly translate back and forth between the mental pictures and textual code. Another possibility is to have the student present a proof of correctness for the algorithm. This is often done by com- ing up with various loop invariants and then proving them correct by induction. Now the student has to really think about why the algorithm works. The low-level details of the implementation need not be considered anymore. One prob- lem with this approach is that the program may be quite large and complicated, thus making a rigorous correctness proof laborious and error-prone. Another problem is that the stu- dent may not be able to easily experiment with concepts as is possible with programming on a computer. Furthermore, the student does not gain the satisfaction of seeing the algorithm execute after having implemented it. In this paper, we show that through visual programming, one can combine various elements of animation, program- ming, and proof so as to teach binary tree algorithms in a more effective manner. In our approach, the student imple- ments a binary tree algorithm by manipulating abstract tree fragments (not necessarily just single nodes) in a visual way. In so doing, the student not only programs the algorithm but also proves some of its properties and can animate it on ex- amples if desired. The remainder of the paper is organized as follows: Sec- tion 2 surveys previous work done on related subjects; Sec- tion 3 presents the visual programming model; Sections 4, 5, and 6 describe visual binary tree depiction, navigation, and manipulation, respectively; Section 7 discusses the correct- ness of the visual binary tree programs; Section 8 describes our current implementation; Section 9 presents preliminary user testing with our system; and Section 10 provides a sum- mary and future research directions. 2 Past Work Many of the elements of our approach have been con- sidered in earlier research, but not all at the same time, and not within the context of an educational visual programming 1

Upload: others

Post on 21-May-2020

11 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Teaching Binary Tree Algorithms through Visual Programmingopsis.sourceforge.net/quals/project.pdf · Teaching Binary Tree Algorithms through Visual Programming Amir Michail Abstract

Teaching Binary Tree Algorithmsthrough

Visual Programming

Amir Michail

Abstract

In this paper, we show how visual programming can beused to teach binary tree algorithms. In our approach,the student implements a binary tree algorithm by manip-ulating abstract tree fragments (not necessarily just singlenodes) in a visual way. This work contributes to visualprogramming research by combining elements of anima-tion, programming, and proof to produce an educationalvisual programming tool. In addition, we introduce Op-sis, a system we built to demonstrate the ideas in thispaper. (Opsis is a Java applet and can be accessed athttp://www.cs.washington.edu/homes/amir/Opsis.html.) Wedescribe our experience with using Opsis in a data struc-tures and algorithms course at the University of Washing-ton. Finally, we make the claim that visual programming isan ideal way to teach data structure algorithms.

1 Introduction

The idea of using computers to teach algorithms is notnew; computer animations are used to illustrate many al-gorithms. Although one might gain insight from watchingan algorithm animation, it is often the case, as with any pass-ive activity, that important details are glossed over or missedaltogether. Indeed, the student may not really understandthe algorithm but merely have a pretense of having doneso. Empirical evidence suggests that students learn betterthrough active rather than passive activities.[9]

A more active method is to have the student implementthe algorithm in some textual programming language. Inthis way, the student must understand the details of the al-gorithm in order to implement it correctly. However, al-though the student may now understand how the algorithmworks, this does not mean the student understands why itworks. Moreover, the student often has to go through thedrudgery of low-level details, such as pointer manipulation,that are not crucial to understanding the algorithm. Worseyet, the algorithm may naturally require the formulation of

mental pictures not readily expressible in code — the stu-dent must constantly translate back and forth between themental pictures and textual code.

Another possibility is to have the student present a proofof correctness for the algorithm. This is often done by com-ing up with various loop invariants and then proving themcorrect by induction. Now the student has to really thinkabout why the algorithm works. The low-level details of theimplementation need not be considered anymore. One prob-lem with this approach is that the program may be quite largeand complicated, thus making a rigorous correctness prooflaborious and error-prone. Another problem is that the stu-dent may not be able to easily experiment with concepts as ispossible with programmingon a computer. Furthermore, thestudent does not gain the satisfaction of seeing the algorithmexecute after having implemented it.

In this paper, we show that through visual programming,one can combine various elements of animation, program-ming, and proof so as to teach binary tree algorithms in amore effective manner. In our approach, the student imple-ments a binary tree algorithm by manipulating abstract treefragments (not necessarily just single nodes) in a visual way.In so doing, the student not only programs the algorithm butalso proves some of its properties and can animate it on ex-amples if desired.

The remainder of the paper is organized as follows: Sec-tion 2 surveys previous work done on related subjects; Sec-tion 3 presents the visual programming model; Sections 4, 5,and 6 describe visual binary tree depiction, navigation, andmanipulation, respectively; Section 7 discusses the correct-ness of the visual binary tree programs; Section 8 describesour current implementation; Section 9 presents preliminaryuser testing with our system; and Section 10 provides a sum-mary and future research directions.

2 Past Work

Many of the elements of our approach have been con-sidered in earlier research, but not all at the same time, andnot within the context of an educational visual programming

1

Page 2: Teaching Binary Tree Algorithms through Visual Programmingopsis.sourceforge.net/quals/project.pdf · Teaching Binary Tree Algorithms through Visual Programming Amir Michail Abstract

tool. Moreover, we believe our approach is enhanced fromthe synergy of many disparate ideas encountered throughoutthe literature.

Much work has been done in algorithm animation. As anexample, the Zeus [1] system animates many fundamentalalgorithms and does so in several ways. However, as we areinterested in abstract representations of trees (i.e, depictinga class of trees, not just one), we draw upon more abstracttree diagrams found in many algorithms and data structurestexts (such as [10, 4]).

Many visual programming systems have been designedfor beginning programmers or application end-users. In theformer group, we find systems like Glinert’s PICT [7], inwhich a programmer uses icons and flowcharts to programsimple arithmetic computations. In the latter group, we findsystems like Modugno’s Pursuit [11], which allows end-users to visually program simple shell scripts by example.However, in both groups, the systems are not designed toteach algorithms, nor do they allow easy construction ofcomplicated algorithms (such as AVL tree insertions or de-letions).

Some visual programming systems have been designedwith more advanced programmers in mind. For example,Christensen’s AMBIT/G [2] and AMBIT/L [3] languageshave been used to manipulate directed graphs and lists,respectively. However, these languages are essentially avisual version of Snobol with static pictures to indicate thepattern matching rules; the resultant programs can be diffi-cult to read and manipulate. Our approach is more dynamic,similar in style to the data structure programming systemThink Pad [13], but easier to use and more abstract.

As we are also interested in visually proving variousproperties of the binary tree algorithms, we borrow someconcepts (primarily loop invariants) from the area of pro-gramming methodology (i.e., formal methods). Indeed, thiswork is inspired by research into how one can implement analgorithm and prove it correct at the same time.[8] However,such efforts make use of complicated first-order logic ex-pressions and are not necessarily suited — as is — for thetask of teaching algorithms.

3 Visual Programming Model

We use a state-based model for representing a program.A user specifies transitions from one state to another by ma-nipulating abstract objects in a visual manner. The idea is tospecify the algorithm in full generality — and not just on aspecific example. For this reason, our approach is not pro-gramming by example [14, 12, 6] but is similar to program-ming by abstract demonstration [5].

3.1 State Types

For our computation model, we use an abstract state,which is an abstract visual diagram that represents a set ofconcrete states (e.g., a set of binary trees). Two abstractstates are identical only if their respective abstract visualdiagrams match exactly. However, we do allow two stateswith exactly the same abstract visual diagrams to not beidentical if the user so desires. This is allowed because wedo not assume that the abstract state completely defines thestate of the program at that point. Finally, it is possible fortwo abstract states to have different diagrams but still rep-resent the same set of concrete states.

For example, an abstract state may represent all binarysearch trees with a node containing a certain key K. Suchan abstract state is shown visually in Figure 1, (4c). Anotherabstract state, different from Figure 1, (4c), but that repres-ents the same set of binary search trees is shown in Figure2, (4).)

In the remainder of the paper, we shall use the word“state” whenever we mean “abstract state”.

3.2 State Graph

Specifically, we model a user-defined function as a stategraph, which is a directed graph whose nodes representstates and whose directed edges represent operations totransform one state to some other(s). Computation starts atthe initial state and ends at one of the final states. In the stategraph, the initial state has no incoming edges and the finalstates have no outgoing edges. (In Figure 1, the initial stateis (1) and the final states are (3b) and (4c).)

(In Figures 1, 2, and 3, the operation shown (textually)below each tree diagram is invoked on the selected frag-ments, which are denoted by dashed lines.)

3.3 Sequencing, Iteration, and Condition-als

The state-based model subsumes sequencing, iteration,and conditionals — no additional control flow constructs arerequired. Sequencing is accomplished though simple trans-itions from one state to another. Iteration is done by creat-ing cycles in the state graph. Conditionals are done throughoperations which result in two or more states. (In Figure 1,sequencing occurs from (4b) to (2), iteration occurs in (2),(3a), (4a), (2), and a conditional occurs from (2) to (3a) and(3b). Observe that the loop ends when the subtree being ex-panded in (2) is empty.)

2

Page 3: Teaching Binary Tree Algorithms through Visual Programmingopsis.sourceforge.net/quals/project.pdf · Teaching Binary Tree Algorithms through Visual Programming Amir Michail Abstract

expand

compare

K

(1) (2)

(3a)

(3b)

(4a) (4b)

(4c)

collapse collapse

fragmentinsert empty

Figure 1. Visual code for binary tree search.

4 Visual Binary Tree Abstractions

In this paper, we describe a visual formalism for imple-menting dictionary “search”, “insert”, and “delete” opera-tions via binary search tree algorithms. This will be doneby manipulating nodes and fragments in a visual way.

4.1 Fragments and Subtrees

Before we proceed, we need to introduce the notion of afragment: a fragment is a (possibly empty) connected sub-graph of a binary tree. A fragment is similar to a subtree inthat it consists of a root node and descendents of that node.Unlike a subtree, a fragment need not include all descend-ents of its root.

4.2 Visual Depiction of Nodes and Frag-ments

Visually, we use a circle to represent a node and a triangleto depict a (possibly empty) tree fragment. We color nodesand fragments to indicate various properties that they mayhave. For example, pink indicates keys less than a certainkey K while the darker magenta indicates keys greater thanK. (See Figure 1, (4a).)

A fragment may also be colored pink on the left andmagenta on the right. This indicates that the fragment mayhave some nodes with keys less thanK and some nodes withkeys greater than K but that it doesn’t have a node with key

search insert

collapse

collapse

K

K

(1)

(2a)

(2b) (3)

K

(4)

K

(5)

Figure 2. Visual code for binary tree insertion.

K. (For example, see Figure 1, (3b).) The vertical bound-ary between the pink and magenta indicates a path of nodes,(x1; x2; : : : ; xj), such that:

1. the key at each xi is not K; and

2. xi is the left (resp. right) child of its parent xi�1 if andonly if K is less (greater) than the key at xi�1.

Intuitively, this path is the path followed if we search thebinary tree looking for key K. Consequently, we call it asearch path.

(In Figure 6, (a), bottom, we show: (1) an abstract treediagram with the upper fragment consisting of pink andmagenta halves; (2) a sample binary tree from the class oftrees represented by the abstract tree diagram. In this case,we were searching for the key ‘L’. The nodes representedby the vertical boundary (separating the pink and magentahalves) have keys ‘O’ and ‘H’.)

A green node labeled K indicates that the node has thedesired key K, while a green fragment labeled K indicatesthat the (non-empty) fragment has a node in it which has keyK. (In Figure 1, (4c), a node with key K is explicitly shownin the tree. In Figure 2, (4), we just know that some node inthe tree has key K.)

5 Visual Binary Tree Navigation

The user can navigate around a binary tree by changingthe nodes and fragments explicitly visible in the tree. Thisapproach is flexible and more natural than using pointervariables (as is done in textual programming languages).There are three main operations for navigation: expand, col-lapse, and insert empty fragment.

5.1 Expand

The expand operation allows one to see an additionalnode in a binary tree fragment if one exists, or to otherwise

3

Page 4: Teaching Binary Tree Algorithms through Visual Programmingopsis.sourceforge.net/quals/project.pdf · Teaching Binary Tree Algorithms through Visual Programming Amir Michail Abstract

search

K

collapse

remove

K

K

expand

K

K

K

collapse

K

remove

(1)

(2a)

(3a)

(3b)

(4a)

(4b)

(5)

(6a)

(6b)

(7)

(8)

collapse

collapse

(9)

insert emptyfragment

remove

K

expand

expand

(2b) (10)

Figure 3. Visual code for binary tree deletion.

determine that the fragment is empty. (In Figure 1, (2), weuse the expand operation to show the root node of the selec-ted subtree if the subtree is non-empty (as in state (3a)), orto indicate that the subtree is empty (as in state (3b)).)

If the fragment being expanded is non-empty, then theparticular node that will be shown depends on whether thefragment is a subtree or not. If the fragment is a subtree, thenthe fragment expands into a node (i.e., the root) connected toits left and right subtrees. (This is what happened in Figure1, (3a).)

If the fragment is not a subtree then there is some node(or fragment) below it. In this case, the fragment expandsby showing the parent of that node (resp. fragment). As thatparent may have the node (resp. fragment) as its left or rightchild, we have two cases. (In Figure 1, (4c), the top fragmentwould expand by revealing the parent of the node labeledK.) This latter type of expand is useful for moving up ina tree, as one might do to maintain a balanced binary treestructure.

5.2 Collapse

The collapse operation allows one to combine severalfragments into one fragment. The fragments to be combinedmust be adjacent to each other in the tree. (For example, inFigure 1, (4a), we use collapse to combine three tree frag-ments into one, thus yielding state (2).) One can also col-lapse a single node to turn it into a subtree. This can be use-ful in forming a loop invariant for moving up a tree after theinsertion of a node.

The fragments being collapsed may have different prop-erties. Whether the resultant fragment inherits a propertyfrom one of its constituent fragments depends on the type ofthe property and on whether the other fragments have thatproperty:1

1. If the property is disjunctive, then if any of the frag-ments have it, then the resulting fragment will have it.(For example, in Figure 2, (2a), the resultant fragment,(4), inherits the property that “it contains a node withkey K” because that property is disjunctive.)

2. If the property is conjunctive, then all fragments musthave it for the resulting fragment to have it. (For ex-ample, in Figure 2, (2a), any property signifying nodeswith keys less than or greater than K are not pre-served in (4) because such properties are conjunctive.However, in Figure 3, (6a), the fragments to be col-lapsed all have the property that “all nodes have keysgreater than K”, so the resultant fragment, in (5), re-tains this property.)

1Similar rules can be formulated for “expand”, but we shall not do sohere.

4

Page 5: Teaching Binary Tree Algorithms through Visual Programmingopsis.sourceforge.net/quals/project.pdf · Teaching Binary Tree Algorithms through Visual Programming Amir Michail Abstract

5.3 Insert Empty Fragment

The insert empty fragment operation allows one to insertan (initially) empty fragment anywhere in the abstract bin-ary tree. In doing so, we obtain a new state that representsa possibly larger class of binary trees that includes all thoserepresented earlier. Inserting empty fragments in this wayallows us to create loop invariants, which we use to formloops.

Whenever we insert a fragment, it is initially empty. Thismeans we can make the new fragment have any property wedesire — as long as that property doesn’t imply the exist-ence of a node. (For example, in Figure 1, (1), (2), we addan empty fragment with the property that “no node have keyK” and that the fragment’s child “is on the search path”.)

5.4 An Example

We have now described various ways to navigate arounda binary tree. These concepts are sufficient to understandthe binary tree search algorithm shown in Figure 1. The al-gorithm is executed on an sample tree in Figure 6, (a).

Initially, we prepare to search for the key K in the treeby adding an initially empty fragment above the currentlyselected subtree (in state (1)). This new fragment doesnot have any nodes with key K (so half of the fragmentis colored pink while the other half is colored magenta).Moreover, the new fragment’s child (i.e., the subtree) is onthe search path. Upon adding the empty fragment, we obtainthe the loop invariant for the search (shown in state (2)).

At this point, we wish to determine whether there is anode with keyK in the selected subtree (in state (2)). So, weexpand the subtree, and depending on whether the subtree isempty or not, we obtain state (3b) or state (3a), respectively.If the subtree is empty, then we have shown that no node inthe binary tree has key K.

If the subtree is not empty, then we have revealed its rootnode. We now compare this node’s key with K. The com-parison yields one of three states (4a), (4b), (4c) dependingon whether the node’s key was greater than, less than, orequal to K, respectively.

If the node’s key is equal to K, then we have found thenode and we are done. Otherwise, we are in state (4a) or(4b). At this point, there is still a subtree which might con-tain a node with key K. So, we collapse the other fragments(which we know do not containK) to obtain the loop invari-ant in state (2). In this way, we have formed a loop by match-ing the loop invariant.

In Figure 6, (a), we show the execution trace of this al-gorithm on a sample binary tree. (This trace was generatedby the Opsis system, which we describe in Section 8.)

6 Visual Binary Tree Manipulation

None of the operations of Section 5 actually change thebinary tree in any way. In this section, we present some op-erations that do make changes.

6.1 Insert Node

The operation insert is used to put a new node in a binarytree. The insert operation changes the structure of the tree,so if the user is working with a binary search tree, it may bethat the insertion destroys the key ordering property of thetree. To avoid this problem, insertions are only allowed ifthe user has established that the point of insertion is indeedthe right location for the key K – that is, that the insertionlies on the search path. (In Figure 2, (2b), the user has estab-lished that the insertion point lies on the search path so thehe can now insert the node with key K at that point. Afterthe insertion, the search path is no longer required. Corres-pondingly, the top fragment changes color to yellow whichindicates keys not equal to K. We also use blue to indicatea region that includes the inserted node such as in states (3)and (5).)

6.2 Remove Node

The operation remove is used to take out a node from abinary tree. If the node to be deleted has at most one child,then the remove operation on that node is sufficient. Ob-serve that taking out a leaf or node with one child cannotdestroy the key ordering property of a binary search tree. (InFigure 3, the remove operation is illustrated in states (3b)and (4b). After the deletion, the search path is no longer re-quired. Consequently, the top fragment changes color to yel-low which indicates keys not equal to K. We also use red toindicate a region that was previously a child of or containingthe node being deleted; see states (7) , (8), and (10).)

If the node to be removed has two children, then the usermust first find the inorder predecessor or inorder successornode of K. In this case, the operation moves the node in-formation from the inorder predecessor (or successor) to thenode and removes the inorder predecessor (resp. successor),which has at most one child, from the tree. (As an exampleof such a case, see Figure 3, (6b) and (9).)

6.3 Other Operations

One can add other operations as required that manipulatea binary tree. For example, for implementing balanced bin-ary search trees, we provide “rotate left” and “rotate right”operations. We also provide “compare info” and “updateinfo” for maintaining additional information in the nodessuch as balance numbers for AVL trees. (To see some of

5

Page 6: Teaching Binary Tree Algorithms through Visual Programmingopsis.sourceforge.net/quals/project.pdf · Teaching Binary Tree Algorithms through Visual Programming Amir Michail Abstract

these operations in action, refer to Figure 7 (a), (b), and (c)for sample execution traces of splay tree insertion, AVL treeinsertion, and red-black tree insertion algorithms, respect-ively.)

Generally speaking, one should provide operations thatare high-level but that do not trivialize the algorithm beingtaught. Moreover, we provide only operations that maintainthe key ordering property of the binary search tree; other-wise, we feel that the operation is too low-level and errorprone.

6.4 More Examples

We consider the binary tree insertion and deletion al-gorithms in Figures 2, and 3, respectively. The insertion anddeletion algorithms are executed on sample trees in Figures6, (a) and (b), respectively.

In the binary tree insertion code, we first perform a search(as defined in Figure 1) for key K in the tree. This yieldstwo cases: either a node with key K is found (state (2a)) orno such node exists in the tree (state (2b)). If we found anode with key K, we simply collapse the fragments in thetree (to yield state (4)). If not, we must insert a node withkey K. However, in state (2b), we have explicitly identifiedthe search path for key K. Thus, we can simply insert thenew node. Finally, we collapse the resulting fragments toyield state (5).

In the binary tree deletion code, we again perform asearch for key K in the tree. If no node has key K, thenwe are done (as in state (2b)). Otherwise, we have a statewith the node with key K explicitly shown (as in (2a)). Atthis point, we check if the node with key K has less thantwo children. If so, then a simple “remove” operation suf-fices. (We check for a left child in states (2a) and for a rightchild in states (3a). The results of the deletion are shown instates (7), (8), and (10).) If the node with key K has twochildren, then we find its inorder successor so that we candelete the node with the more complex form of the opera-tion “remove”. We start the search for the inorder successorby adding an initially empty fragment above the node’s rightchild so that the right child is on the leftmost path in thatfragment (as shown in states (4a), (5)). Now, using a com-bination of “expand” and “collapse”, we descend left alongthe nodes until we reach the inorder successor (as is donewith the loop in states (5), (6a) which eventually terminatesto yield (6b)). Next, we invoke the “remove” operation onthe node with key K to perform the deletion (as is done instates (6b), (9), and (10)).

7 Correctness

The visual programs presented in Figures 1, 2, and 3 areclose to also being correctness proofs.

For example, consider the binary tree search program inFigure 1. State (2) at the head of loop (2), (3a), (4a/b), (2)is a visual loop invariant. The proof that this loop invari-ant holds is also shown visually: in the first iteration, theloop invariant holds vacuously because the fragment inser-ted is empty; in subsequent iterations, the sequence (2), (3a),(4a/b), (2) preserves the loop invariant (as long as no matchis made yet). Thus, the loop invariant in state (2) is provedby structural induction in a visual way.

From the visual program, we know that if the programterminates, then it will either find the node with key K orassert that no such node exists. However, the program doesnot show that the algorithm terminates or how long it takesif it does.

Generally speaking, our visual formalism allows the userto prove certain structural properties about the tree structureand also ensures that the key ordering of binary search treesis maintained. However, for complicated algorithms, onemay need to prove other properties that are not readily en-coded in the tree diagrams. In this case, we recommend thateither the student simply not prove such properties, or thathe annotate the states with English text to fill in the detailsof the proof.

8 Implementation

We have been working on a system named Opsis, whichimplements the model and domain described in Sections3–6. (The word “opsis” is Greek for the visual image ofan object.) Opsis is a Java applet and can be accessed athttp://www.cs.washington.edu/homes/amir/Opsis.html.A snapshot of the system is shown in Figure 4.

8.1 User-Interaction

A user implements an algorithm by starting out with theinitial state and repeatedly invoking operations on one of thefinal states at each point. (For convenience, the user is al-ways presented with a history of the computation and a listof all final states at every step of the process; see Figure 4.)This process continues until the only remaining final statesin the program represent valid results of the algorithm beingdefined.

In particular, a user creates a state graph by concentratingon one state at a time. The user selects by mouse some treefragment(s) in the current state and invokes an operation onthat selection. Invoking an operation causes the creation oftransitions from the current state to one or more other res-ultant states. One of these resultant states (chosen arbitrar-ily if there is more than one) replaces the current state onthe screen. Thus, creating a program is akin to designing an“abstract animation” for the algorithm. Also, if any of theresultant states match one already in the program, then the

6

Page 7: Teaching Binary Tree Algorithms through Visual Programmingopsis.sourceforge.net/quals/project.pdf · Teaching Binary Tree Algorithms through Visual Programming Amir Michail Abstract

Figure 4. The binary tree deletion algorithm developedin the Opsis system. Editing occurs on the current statewhich dominates much of the display. On the right, a se-quence of states show a history of the computation thatleads to the current state. Observe the arrow in the statehistory list: this arrow indicates that the operation onthe state at its tail of the arrow yields the state at its head(thus indicating a loop). At the bottom, the final statesof the computations are shown (i.e., these are states atwhich the computation terminates). The user may addcomments to the state in the white region near the top.Finally, observe the bubble help which explains what thevarious property colors mean.

current state is linked to the one already present if the userso wishes; otherwise new states are created as required. Onemay instruct Opsis to avoid matching two states even if theirvisual diagrams are identical because the two states are ac-tually different — but the visual formalism is insufficient todistinguish them.

(A sample session using Opsis is shown in Figure 5. Inthis figure, the user has implemented the binary tree searchalgorithm: (a) shows the initial state; (b) shows the state ob-tained after inserting an empty fragment; (c) shows the statein which the keyK is found; and (d) shows the case in whichthe key in the node shown is too small so a collapse opera-tion is performed to match the loop head in order to furtherexplore the right subtree.)

8.2 Imitate Commands

In many balanced binary tree algorithms, such as withAVL trees, one often has to deal with large computationsthat are simply mirror images of one other. To reduce theprogramming effort for such computations, the student maysimply implement the algorithm for one case, and then haveOpsis automatically generate states for the mirror imagecase. Specifically, the user can invoke the “imitate mirrorimage” command on the current state. Opsis then looks forthe mirror image state and performs a traversal of the stategraph at that location so as to generate the new mirror statesfor the mirror image case. Although this command is a heur-istic, we found it usually leads to the desired results.

It may also be the case that the user may wish to repeatthe same code several times in the algorithm. For example,to implement the splay algorithm, one repeats similar codefor three cases that arise depending on whether we bubble upthe node with key K, its inorder predecessor, or its inordersuccessor. Moreover, at times we may even want to imple-ment the same code even though the states in each case havetrees with slightly different structures. For example, in anAVL insertion algorithm, one might implement the rotationsinvolving the inserted node as a special case, and then usesimilar code for rotations higher up in the tree (that do notinvolve the inserted node). To do this in Opsis, the user se-lects a state, moves to the similar state, and invokes the “im-itate selected state” command. This will perform a traversalof the state graph starting at the selected state so as to gen-erate states for the similar case. Again, this command is aheuristic. Unlike the “imitate mirror image” command, thiscommand may ask the user for advice on whether to changeinformation stored at the node in the same way or whetherto match a state encountered earlier or to ignore the match.The heuristic usually leads to the expected results.

It may appear that the “imitate” commands are an un-necessarily complicated way to program without functions.Indeed, our motivation for these commands is to allow the

7

Page 8: Teaching Binary Tree Algorithms through Visual Programmingopsis.sourceforge.net/quals/project.pdf · Teaching Binary Tree Algorithms through Visual Programming Amir Michail Abstract

(a) (b)

(c) (d)

Figure 5. Construction of the binary tree search algorithm in Opsis.

8

Page 9: Teaching Binary Tree Algorithms through Visual Programmingopsis.sourceforge.net/quals/project.pdf · Teaching Binary Tree Algorithms through Visual Programming Amir Michail Abstract

user to program without worrying about structuring theircode. That is, they can simply program on a flat state space.There are several advantages to this approach: (1) the stu-dent can concentrate on the algorithm rather on how to struc-ture code for the algorithm; (2) the visual abstractions canbe kept simple as there is no need to represent functions (ortheir parameters) and modules; and (3) the user need notconsider all cases at once, but just work on one at a time.

9 User Testing

We have done some preliminary user testing with stu-dents taking CSE 373, a third year data structures course fornon-majors at the University of Washington. Students in thisclass typically major in engineering, math, or science.

Students in CSE 373 were required to do a final projectwith one of the possible topics involving Opsis. In the Opsisproject, the students implement two balanced binary searchtree algorithms of their choice. (For example, AVL insertioncounts as one algorithm.) Both algorithms could be done inOpsis or one in Opsis and another in a standard textual pro-gramming language. (Most students chose C++ as a textuallanguage.) Students could work alone or in pairs.

Students were given a tutorial and documentation on thebasics of the Opsis system. However, we did not explain tothem the balanced binary search tree algorithms; they had tounderstand them on their own from various texts.

Ultimately, eight groups chose to do their final courseproject using Opsis. Three of these groups consisted ofpairs. The following observations are based on the studentreports and a questionnaire. Although our user testing didnot include enough students for a statistically significantstudy, we were able to obtain insight into the experiencesstudents had with the Opsis system.

9.1 Learning Curve and ImplementationSpeed

One of the reasons we built Opsis was to provide away for students to implement complicated tree algorithmswithout worrying about low-level implementation details.In particular, students need not perform any pointer manip-ulation nor structure their code in any way (eg., using func-tions or modules). In so doing, we hoped that students wouldconcentrate more on the actual algorithm rather than on im-plementation details.

We were partially successful. Although students indic-ated that Opsis had a non-trivial learning curve, they alsosaid that once they understood the system, they were ableto implement tree algorithms quickly.

Students typically spent 1–5 hours to learn Opsis. Ofcourse, there was almost no initial learning period for textual

languages as the students were already quite familiar withthem.

After the initial learning period, students spent aboutabout 2–20 hours per algorithm using Opsis. Simpler al-gorithms such as Splay tree algorithms took about 2–10hours while more complicated algorithms such as those forAVL tree took between 7-20 hours.

Surprisingly, students spent roughly the same time withtextual programming languages. However, one group wasnot able to implement the Splay tree algorithms in C++ at all.Time for the AVL tree algorithms varied from 2–20 hours.(The students did not report any times for the splay tree al-gorithms implemented using textual code.)

We expected the Opsis implementation times to be sig-nificantly less — not roughly about the same as those fortextual code. However, there is tremendous variation in thetimes observed – probably a result of the variation in the stu-dents’ abilities and background. Thus a much larger sampleis necessary to test this hypothesis. Moreover, some stu-dents copied textual code fragments from books. Others ex-perienced technical problems with Opsis, which were even-tually resolved.

9.2 Learning Visually versus LearningTextually

As mentioned earlier, we did not have enough studentsfor a statistically significant study. However, from our ex-perience, we found little difference in how well studentslearned algorithms in Opsis versus textual programminglanguages. Of course, students who implemented the al-gorithm using a textual programming language had a bet-ter idea of how to move pointers about in a low-level imple-mentation. On the other hand, for some students the textualimplementation took longer or was too difficult to do.

9.3 Proof versus Programming

One interesting aspect of Opsis is that it completely blursthe distinction between programming and proof. Certainly,the creation of loop invariants and structural induction argu-ments is a process close to proof. Yet, other operations feellike programming.

We found it interesting that most students said imple-menting algorithms in Opsis felt more like programmingthan proof. However, one student disagreed: “most of thetime I am programming in Opsis, I treat it as a ‘proof”’. In-terestingly, this student, more so than the others, felt that hisextensive programming experience in textual languages wasa hinderence to using Opsis. Thus, the move to Opsis madethe system appear very proof oriented.

Possibly another reason why most students saw imple-mentation in Opsis as mostly like programming is that they

9

Page 10: Teaching Binary Tree Algorithms through Visual Programmingopsis.sourceforge.net/quals/project.pdf · Teaching Binary Tree Algorithms through Visual Programming Amir Michail Abstract

(a) (b) (c)

Figure 6. Opsis execution traces. The algorithms shown are: (a) binary tree search; (b) binary treeinsertion; and (c) binary tree deletion.

10

Page 11: Teaching Binary Tree Algorithms through Visual Programmingopsis.sourceforge.net/quals/project.pdf · Teaching Binary Tree Algorithms through Visual Programming Amir Michail Abstract

(a) (b) (c)

Figure 7. Opsis execution traces. The algorithms shown are: (a) splay tree insertion; (b) AVL treeinsertion; (c) and red-black tree insertion.

11

Page 12: Teaching Binary Tree Algorithms through Visual Programmingopsis.sourceforge.net/quals/project.pdf · Teaching Binary Tree Algorithms through Visual Programming Amir Michail Abstract

were unsuccessful in forming loop invariants for complic-ated algorithms. Most of their experience was with parts thatfelt like programming.

9.4 Debugging

Strictly speaking, we did not need to allow students torun their algorithms on examples. This is because an Op-sis program, when properly commented, should be close toa proof of correctness for the algorithm. However, Opsisdoesn’t completely enforce correctness during implement-ation so mistakes may still occur. (Although Opsis enforceslow-level correctness dealing with pointers and tree struc-ture, it doesn’t enforce high-level correctness dealing withinformation stored at the nodes or amortized analysis ar-guments.) Moreover, we felt that showing the student thecorrespondence between the visual states and the concretestates during execution would be helpful in clarifying the ab-stractions and the algorithm itself.

Indeed, the ability to execute a program turned out to bequite important. Many students indicated that half of theirtime was spent programming new code while the other halfwas spent debugging (i.e., repeated execution). We believethere are primarily two reasons for this. First, students likeincremental development even if they have a proof of cor-rectness – they would still like to check the proof. Second,students obtain a sense of satisfaction from executing code.

9.5 Visual Clutter

Several students complained that it was difficult to keeptrack of all the graph states particularly for the more com-plicated AVL and red-black tree algorithms. We anticipatedthis problem and created the final and history state lists toalleviate the visual clutter. However, one student felt thatthis restricted view to the state graph was a actually a prob-lem because it was easy to become lost in the numerous al-gorithm states. She said “When a change was made and Iprogressed to the next state it was almost impossible to findwhere I had previously been working.”

Another student who was implementing the red-blacktree insertion algorithm complained that Opsis requiredmore states than necessary because: (1) it kept track ofwhich subtree the key was inserted in which is not necessaryfor the red-black insertion algorithm (but necessary for theAVL tree insertion algorithm); and (2) it didn’t allow one toconsider nil pointers as black nodes (which would reduce thenumber of cases in the red-black tree algorithm). Althoughit is easy to automatically generate these additional states bythe “imitate” commands, we can see how new users of thesystem may view this as unnecessary work and a factor inthe visual clutter problem.

9.6 Guidance versus Flexibility

One of our goals with Opsis was to provide the studentwith some guidance without giving away the solution to analgorithm. This principle permeates throughout our design.For example, we hide the details of pointer manipulation,provide functions to perform rotations automatically, keeptrack of which subtree an insertion occurs in, and keep trackof where a deletion occurs.

Another goal was to allow the student to program withoutcreating any structure in the code. That is, programming isdone on a flat state space without any functions or modules.The purpose for doing this is to allow the student to concen-trate only on the algorithm and not on how to structure codeto implement the algorithm. In addition, we provide “imit-ate” commands to handle similar cases automatically in theflat state space. By avoiding program structure, we “guide”the student towards the algorithm and away from structur-ing code. (That is, students can’t structure code even if theywant to.)

Unfortunately, this guidance has a price — flexibility.Several students complained that they had very little free-dom in the way they implemented an algorithm. One studentwrote “it has more guideline than a high-level programminglanguage such as C++ but it has less flexibility for the pro-grammer.” (Indeed, most implementations for the same al-gorithm were very similar.) Although we view this as an ad-vantage of using Opsis, it turns out that this lack of freedomhinders the progress of some students.

9.7 Graphical Abstraction

The learning curve mentioned earlier is partly a resultof the graphical abstraction. Most students found the ab-stract states confusing at first but became proficient withthem after some experimentation. One student wrote “Ittakes some getting used to think in tree fragments. Once Iam in the ‘mode’, I don’t have any problem with the abstractrepresentation of the tree structure.” A few students wereconfused about how a state before an operation correspondsvisually to one after the operation. (This is probably due tothe way the fragments move about automatically when thetree is changed.)

Students generally agreed that the graphical representa-tion allowed them to “see” the algorithm clearly. One stu-dent wrote “The ability to see an algorithm take shape onthe computer screen was an incredibly valuable learning ex-perience.” Another wrote “the ability to manipulate abstracttree fragments versus dealing with the switching of pointersmakes the algorithm much more understandable and easierto learn”.

Some students found their extensive experience in tex-tual programming languages made it harder to learn Opsis.

12

Page 13: Teaching Binary Tree Algorithms through Visual Programmingopsis.sourceforge.net/quals/project.pdf · Teaching Binary Tree Algorithms through Visual Programming Amir Michail Abstract

A student wrote “All the books I have read and the classesthat I have attended were all in textual languages, so I canthink much faster in a textual language than I can in Opsis.”On the other hand, students who said they think better visu-ally found the graphical abstractions to be very valuable.

9.8 Loop Invariants

We expected students to have trouble with building loopinvariants while implementing algorithms. However, webelieved this to be such a valuable activity that we madeloop invariants very explicit in Opsis. Indeed, programs im-plemented in Opsis are essentially structural induction argu-ments with the visual loop invariants being the induction hy-potheses.

As there is no automated way to come up with a goodloop invariant, the process involves guessing and intuition.One student wrote “On the first try, I had lots of troublebuilding loop invariants.” The problem was particularlyacute with the more complicated AVL tree algorithms. In-deed, no group was successful in implementing a completeAVL tree insertion algorithm because they couldn’t come upwith a suitable loop invariant. (Their implementations onlyhandled cases where the rotations are done at the base of thetree just after insertion.) However, students were able to dothe simpler splay tree algorithms.

We believe explicit loop invariants clarify the algorithmand make its correctness proof more apparent. One studentwrote: “finding the loop invariants helped to solidify the re-cursive nature of binary tree algorithms in my mind and thegraphic nature of the program allowed me to actually see theloop.”

9.9 Demonstrating Concepts

Although our motivation behind Opsis was to allow stu-dents to implement algorithms through visual programming,several students suggested other uses. In particular, stu-dents suggested that Opsis might be useful for demonstra-tion. For example, a professor might demonstrate an al-gorithm in class by using Opsis. Unlike standard algorithmanimations, an Opsis demonstration can be more interactiveand can actually show the students the abstract loop invari-ants and structural induction arguments for the algorithm. Inthis way, Opsis can be useful in enhancing written textualproofs by showing key steps in an abstract visual manner.

9.10 Teaching Non-majors

Most universities have computer science courses for stu-dents majoring in other disciplines. From our experiencewith CSE 373, it is clear that some of these students do nothave the same programming abilities as computer science

students. Consequently, Opsis may be particularly suitablefor such classes as it allows the professor to assign complic-ated algorithms in such a way as to avoid laborious low-levelimplementation details that would otherwise discourage stu-dents. (Of course, we do not advocate only using Opsis insuch courses; implementation with a textual programminglanguage is still essential.)

10 Conclusion

In this paper, we have proposed a new way to teach binarytree algorithms through visual programming. We believethat this approach better allows a student to implement analgorithm while concentrating on why it works rather thanon low-level implementation details. Moreover, our visualapproach not only yields a program but also a proof of someproperties maintained or that result from the computation.

To validate our approach, we have built a Java applet,named Opsis, that demonstrates the ideas in this paper. Inaddition, we have performed a user study in a data structurescourse. From this experience, we found that although Opsishas a non-trivial learning curve, students were able to learnand use the applet to implement the various algorithms. Wealso found students felt the system clarified the algorithmsby making tree structure and loop invariants explicit visu-ally. It would be of interest to conduct a more extensivestudy to determine how much faster (if at all) students canimplement algorithms with Opsis as compared to textualprogramming languages.

Finally, we believe visual programming is not only agood way to teach binary tree algorithms (and more gener-ally, data structures), but also a promising way to teach al-gorithms in other fields. It would be interesting to exploresuch possibilities further.

11 Acknowledgments

I would like to thank Steve Tanimoto for careful read-ing of this paper, helpful suggestions, and encouragementthroughout this research. I would like to thank David Notkinfor reading a later version of this paper. I would also like tothank Rick Hehner for insights obtained from his theory ofprogramming.

Funding for this research was provided by the NaturalSciences and Engineering Research Council of Canada.

References

[1] M. H. Brown. Zeus: A system for algorithm animation andmulti-view editing. In IEEE Workshop on Visual Languages,pages 4–9, October 1991.

13

Page 14: Teaching Binary Tree Algorithms through Visual Programmingopsis.sourceforge.net/quals/project.pdf · Teaching Binary Tree Algorithms through Visual Programming Amir Michail Abstract

[2] C. Christensen. An example of the manipulation of dir-ected graphs in the AMBIT/G programming language. InM. Klerer and J. Reinfelds, editors, Interactive Systems forExperimental Applied Mathematics, pages 423–435. Aca-demic Press, 1968.

[3] C. Christensen. An introduction to AMBIT/L, a diagram-matic language for list processing. In Proceeding of the 2ndSymposium on Symbolic and Algebraic Manipulation, pages248–260, 1971.

[4] T. H. Cormen, C. E. Leiserson, and R. L. Rivest. Introductionto Algorithms. MIT Press, 1991.

[5] G. A. Curry. Programming by Abstract Demonstration.Technical Report 78-03-02, University of Washington, 1978.

[6] A. Cypher, editor. Watch What I Do. MIT Press, 1993.[7] E. P. Glinert. PICT: Experiments in the Design of Interact-

ive, Graphical Programming Environments. Technical Re-port 85-01-01, University of Washington, January 1985.

[8] E. C. R. Hehner. A Practical Theory of Programming.Springer-Verlag, 1993.

[9] A. W. Lawrence, A. M. Badre, and J. T. Stasko. Empiric-ally evaluating the use of animations to teach algorithms. InSympsoium on Visual Languages. IEEE, October 1994.

[10] H. R. Lewis and L. Denenberg. Data Structures and TheirAlgorithms. Haper Collins, 1991.

[11] F. Modugno and B. Myers. A state-based visual languagefor a demonstrational visual shell. In Sympsoium on VisualLanguages. IEEE, October 1994.

[12] B. Myers. Visual programming, programming by example,and program visualization; A taxonomy. In Proceedings ofCHI ’86, pages 59–66. ACM, April 1986.

[13] R. V. Rubin, E. J. Colin, and S. P. Reiss. Think pad: A graph-ical system for programming by demonstration. IEEE Soft-ware, 3:73–78, March 1985.

[14] S. D. Smith. Pygmalion: A Creative Programming Envir-onment. Technical Report STAN-CS-75-499, Stanford Uni-versity, 1975.

14