• Keine Ergebnisse gefunden

S. Using Pointers to Construct a Binary Tree

10.S. The Expression Statement

II. S. Using Pointers to Construct a Binary Tree

The program of Example 11.5-2 uses a data structure known as a binary tree to alphabetize a series of strings. The strings are read in, one per line, from a file; as each is read, it is added to the binary tree. The tree is maintained in such a way that if it is printed out in "infix order", the result is an alphabetized list.

Each node in the tree consists of three fields: two pointers and a string. The "left" pointer points to a subtree of strings alphabetically preceding the string field; the "right" field, to a subtree of strings following the string field. See Example 11.5-1. Note that all the words on the branch descending from the left of a given word alphabetically precede it; all those descending from the right of a word follow it.

owl

/ \

cat zebra

/

\

ape fish

\ lemming

Example 11.5-1. A Binary Tree of Strings

To maintain the tree in this alphabetical order, each new word must be added according to the following algorithm:

1. Set the "current node" to be the root of the tree (e.g., the "owl" node in Example 11.5-1).

2. If the current node is nullPointer, add the new word at the current node and stop.

3. If the new word alphabetically precedes the word at the current node, set the current node to be the node down to the left; if it follows the current word, set the current node to be the node down to the right. If the new word is the same as the word at the current node, stop (Le., don't put it in the tree twice); otherwise, go back to step 2.

Printing the tree in infix order means printing the strings of the left subtree of each node (in infix order), then the string at this node, then the strings of the right subtree (in infix order).

This is a recursive algorithm, and is implemented in Example 11.5-2 as a recursive procedure.

If you are unfamiliar with the notion of "infix order", you may be excused if you have to think about this for a while to verify that it works.

Note that the tree constructed by this algorithm does not necessarily have the same shape if the order of the input strings is altered; however, it always comes out in proper alphabetical order if printed in infix order.

BEGIN "binTre"

*

Use a binary tree to alphabetize the lines in a text

*

file.

CLASS bin

) ;

POINTER (bin) left, right;

STRING here;

POINTER (bin) root;

Example 11.5-2. Use of Pointers to Construct a Binary Tree (continued)

PROCEDURE alphabetize (STRING s; MODIFIES POINTER (bin) p);

# If

P

is nullPointer, create a node for i t containing s.

# If P is not nullPointer, add a node on the left subtree

# if s precedes p.here, on the right subtree if i t

# follows. If i t ' s the same as a node already there,

# don't add i t . BEGIN

IF NOT P THENB

*

create the node

p :- new(bin)i p.here :- Si RETURN ENDi CASE compare(s,p.here,upperCase) OFB

[-1] alphabetize(s,p.left);

[0] RETURN;

[1] alphabetize(s,p.right);

END;

END;

PROCEDURE infixPrint (POINTER (bin) p);

BEGIN

IF NOT P THEN RETURN;

infixPrint(p.left) ;

write(logFile,p.here,eol);

infixPrint(p.right) ; END;

INITIAL PROCEDURE;

BEGIN STRING s;

POINTER (textFile) f;

open(f,"Input file: ",input!prompt)i

DOB read(f,s); IF NOT $gotValue(f) THEN DONE;

IF s THEN alphabetize(s,root) END;

close(f) ;

infixPrint(root);

END;

END "binTre"

Example 11.5-2. Use of Pointers to Construct a Binary Tree (end)

11.6. Exercises

Exercise 11-1.

Which records in Example 11.1-5 are accessible from p? Which from q? For each record accessible from p, construct an expression beginning with p that points to the record (e.g., Itp.p1.plt points to REC 3); do the same for q.

Exercise 11-2.

Write a program that sorts strings using a linear list rather than a binary tree. Which algorithm would you expect to run faster?

12. Arrays; the System Procedure cmdMatch

This chapter describes the array, a random-access data structure. MAINSAIL arrays may have one, two, or three dimensions. Like records, arrays are subject to garbage collection.

12.1. Lists and Arrays

The linked list constructed of records used in Chapter 11 is used to store a series of pieces of information in memory. It is a satisfactory data structure when you want to find an item based on some characteristic of the item, as in the program of Example 11.3-1, where a search is based on the string "name" field of a record.

Items in a series of things are often accessed by number. To find the tenth item in a linked list, you must start a search at the first item in the list and progress through the items one by one until you reach the tenth. The MAINSAIL array data structure provides a more efficient (and syntactically more convenient) means of accessing an item by number.

An array consists of a number of components (called "elements" or "array elements"), all of the same data type. The elements may be of any MAINSAIL data type, but they may not

themselves be arrays (the array is not considered to be a data type). Some sample array declarations appear in Example 12.1-1. The numbers in parentheses following the keyword

"ARRAY" are called "bounds"; the values preceding the keyword "TO" are lower bounds, and those following are upper bounds.

INTEGER ARRAY(O TO 9) digitChars;

. # One integer for every digit

STRING ARRAY(l TO 100) strings; # 100 strings CLASS xxx (

) ;

POINTER (xxx) next;

INTEGER value;

POINTER (xxx) ARRAY(l TO 20,-10 TO 10) yyy;

# A two-dimensional array of 20 x 21

=

420 pointers

Example 12.1-1. Sample Array Declarations

; Unlike most programming languages, MAINSAIL does not allocate arrays when they are declared. Arrays are allocated by the system procedure "new" (a different form of "new" from that described in Chapter 11). To allocate an array by means of "new" is called "to new" the array (to allocate a record is also sometimes referred to as "to new" the record or the pointer variable that points to it). The arrays of Example 12.1-1 are newed in Example 12.1-2. The elements of an array are not accessible until after it has been newed; after the call to "new", all the elements of the allocated array have the Zero value for their data type.

new(digitChars);

new(strings);

new (yyy) ;

Example 12.1-2. Newing Some Arrays

An array element is accessed by placing an integer (or two or three integers if the array is two-or three-dimensional) in square brackets following the name of the array. The integer two-or integers in brackets are called "subscripts", The array name and its bracketed subscript or subscripts together constitute a "subscripted variable". Some sample uses of subscripted variables using the arrays of Example 12.1-1 appear in Example 12.1-3.

digitChars[6] := '6';

*

Element 6 of the array acquires

*

the value that is the character

*

code for the digit "6"

INTEGER i; STRING Si

# Look for the first null string in the array (note the

# use of an Empty Statement as the iterated statement) : FpR i := 1 UPTO 100 WHILE strings[i] DO;

# i has the value 101 if no null string was found:

IF i > 100 THEN errMsg("No null string found")

EL strings[i] ,= Si # Replace the null string with s INTEGER i , j i

# A subscripted variable that is a pointer may be used

# to access fields:

yyy[i,j] := yyy[j,yyy[i,j] ,value] ,next;

Example 12.1-3. Subscripted Variables

An

array variable is acwally a special sort of pointer variable. When the array is allocated, it points at the

data

structure allocated by "new". When one array variable is assigned to another, both array variables are then made to point to the same array; no copying of elements occurs.

If a change is made to an element of the array using one array variable, the changed value is