{ Pascal/Z compiler options } {$C- <<>>} {$M- <<>>} {$F- <<>>} PROGRAM BTREE; { Program title: Binary Trees Demo Written by: Date written: November 1981 Last edited: 11/20/81 rep Pascal compiler: Pascal/Z vers 4.0, Ithaca Intersystems, Inc. Summary: Maintain a sorted list in a binary tree Bibliography: GROGONO, P.: Programming in PASCAL, Addison-Wesley Publishing Co., Reading, MA. TENENBAUM, A. and AUGENSTEIN, M.: Data Structures Using Pascal, Prentice-Hall, Englewood Cliffs, N.J. 07632 WIRTH, N.: Algorithms + Data Structures = Programs, Prentice-Hall, Englewood Cliffs, N.J. 07632 } CONST default = 80; vers = 4; { PROGRAM VERSION NUMBER } TYPE alpha = packed array [1..10] of char; int = integer; str0 = string 0; shorty = string 40; dstring = string default; str255 = string 255; PersonDetails = RECORD Name, { KEY FIELD } Company, address, city, state, zip, salary : shorty; END; apointer = ^PERSON; PERSON = RECORD details : PersonDetails; Left, Right : apointer END; VAR bell : char; Command : CHAR; con_wanted, tty_wanted : boolean; answer : shorty; { Console inputs here } KEY, { Name field is the "KEY" field } New_Salary, New_Company, New_address, New_City, New_State, New_Zip : shorty; STDOUT : FILE OF PersonDetails; Employee : apointer; function length( x: str255 ): int; external; function index( x,y: str255 ): int; external; procedure setlength( var x:str0; y: int ); external; PROCEDURE InitTree( VAR Employee : apointer ); { initialize the tree to empty } BEGIN Employee := NIL END{of InitTree}; PROCEDURE INSERT( VAR Employee : apointer; key : shorty ); { insert key into the tree. If it } { is there already then do nothing } BEGIN IF Employee = NIL THEN BEGIN NEW(Employee); WITH Employee^, details DO BEGIN Name := key; Salary := New_Salary; Company := New_Company; address := New_address; City := New_City; State := New_State; zip := New_Zip; left := NIL; right := NIL END{WITH} END ELSE IF key = Employee^.details.Name THEN WRITELN( bell, key,' already in data file' ) ELSE IF key < Employee^.details.Name THEN Insert( Employee^.left, key ) ELSE IF key > Employee^.details.Name THEN Insert( Employee^.right, key ) END{of INSERT}; PROCEDURE DeleteLeftMost( VAR Employee : apointer; VAR DeleteName : shorty ); { delete the leftmost node in the tree and } { returns its value in DeleteName } BEGIN IF Employee^.Left <> NIL THEN DeleteLeftMost( Employee^.Left, DeleteName ) ELSE BEGIN DeleteName := Employee^.details.Name; Employee := Employee^.right END END{of DeleteLeftMost}; PROCEDURE DeleteRoot( VAR Employee : apointer ); { deletes the root of the nonempty tree by replacing it } { by its successor (or child) if it has only one, or } { replacing its value by that of the leftmost descendant } { of the rightmost subtree. } VAR DeletedName : shorty; BEGIN IF Employee^.Left = NIL THEN Employee := Employee^.right ELSE IF Employee^.right = NIL THEN Employee := Employee^.Left ELSE BEGIN DeleteLeftMost( Employee^.right, DeletedName ); Employee^.details.Name := DeletedName END END{of DeleteRoot}; PROCEDURE Delete( VAR Employee : apointer; key : shorty ); { delete key from the tree--if it is not } { in the tree, do nothing } BEGIN IF Employee = NIL THEN WRITELN ( bell, key, ' not in data file' ) ELSE IF key = Employee^.details.Name THEN DeleteRoot( Employee ) ELSE IF key < Employee^.details.Name THEN Delete(Employee^.Left, key ) ELSE IF key > Employee^.details.Name THEN Delete( Employee^.right, key ) END; PROCEDURE DISPLAY( Employee: apointer ); BEGIN WITH Employee^.details do begin writeln( Name ); if length( Company ) > 0 then writeln( Company ); if length( address ) > 0 then writeln( address ); writeln( City, ', ', State, ' ', Zip ); writeln end END{of DISPLAY}; PROCEDURE Preorder( Employee : apointer ); { prints data from left side of tree to right } BEGIN IF Employee <> NIL THEN BEGIN DISPLAY( Employee ); {visit the root} Preorder( Employee^.Left ); {traverse the left subtree} Preorder( Employee^.Right ) {traverse the right subtree} END END{of preorder}; PROCEDURE Inorder( Employee : apointer ); { prints data outer to inner of tree } BEGIN IF Employee <> NIL THEN BEGIN Inorder( Employee^.Left ); {traverse the left subtree} DISPLAY( Employee ); {visit the root} Inorder( Employee^.Right ) {traverse the right subtree} END END{of inorder}; PROCEDURE Postorder( Employee : apointer ); { prints data from leaves first then branchs } BEGIN IF Employee <> NIL THEN BEGIN Postorder( Employee^.Left ); {traverse the left subtree} Postorder( Employee^.Right ); {traverse the right subtree} DISPLAY( Employee ); {visit the root} END END{of postorder}; {****************************} {*** UTILITY ROUTINES ***} {****************************} PROCEDURE SIGNON; VAR IX : 1..24; BEGIN FOR IX:=1 TO 24 DO WRITELN; WRITELN( ' ':15, 'NAME AND ADDRESS ENTRY PROGRAM Version #', vers ); FOR IX:=1 TO 4 DO WRITELN; { SIGNON TEXT GOES HERE } END{of SIGNON}; PROCEDURE MENU; BEGIN WRITELN; WRITELN; WRITELN( ' ':12, '1 - INSERT MODE' ); WRITELN( ' ':12, '2 - DELETE MODE' ); WRITELN( ' ':12, '3 - DISPLAY MODE' ); WRITELN( ' ':12, '9 - TERMINATE' ); WRITELN; CASE Command OF '1': WRITELN( 'MODE=INSERT' ); '2': WRITELN( 'MODE=DELETE' ); '3': WRITELN( 'MODE=DISPLAY' ); ELSE: WRITELN END{CASE} END{of MENU}; FUNCTION toupper( ch: CHAR ): CHAR; BEGIN IF ( 'a'<=ch ) AND ( ch<='z' ) THEN ch := CHR(ORD(ch) - 32); toupper := ch END{of toupper}; PROCEDURE INPUT( txt: dstring; VAR answer: shorty ); BEGIN WRITE( txt ); READLN( answer ); END{of INPUT}; PROCEDURE LIST; VAR ch : CHAR; OUTPUT : TEXT; BEGIN WRITELN( 'Output to C(onsole or P(rinter? ' ); readln( ch ); con_wanted := ( toupper(ch)='C' ); tty_wanted := ( toupper(ch)='P' ); { one or the other but not both } if tty_wanted then con_wanted := false; if NOT (con_wanted OR tty_wanted) then { listing := false } else begin { listing := true; } if con_wanted then REWRITE( 'CON:', OUTPUT ); if tty_wanted then REWRITE( 'LST:', OUTPUT ); end; WRITELN; WRITELN; Inorder( Employee ); if con_wanted then begin writeln; WRITE( bell, 'PRESS RETURN TO CONTINUE ' ); READLN( ch ); end END{of LIST}{ CLOSE( OUTPUT ); }; BEGIN{ MAIN PROGRAM BLOCK } InitTree( Employee ); bell := chr(7); Command := ' '; SIGNON; MENU; INPUT( 'COMMAND: ', answer ); Command := toupper( answer[1] ); WHILE Command <> '9' DO BEGIN IF Command IN ['1','2','3'] THEN BEGIN WRITELN; CASE Command OF '1': begin { INSERT MODE } REPEAT writeln( 'ENTER:' ); INPUT('1 - NAME !', key ); INPUT('2 - Salary amount <12000> !', New_Salary ); input('3 - Company Name
!', New_Company ); input('4 - Address line 2 !', New_address ); input('5 - City !', New_City ); input('6 - State !', New_State ); input('7 - Zip Code !', New_Zip ); writeln; write( 'DATA OK? ' ); readln( answer ); UNTIL toupper(answer[1])<>'N'; INSERT( Employee,key ); end; '2': begin { DELETE MODE } REPEAT INPUT( 'Enter NAME --> ',key ); writeln; writeln( 'Deleting > ', key ); write( 'OK? ' ); readln( answer ); UNTIL toupper(answer[1])<>'N'; Delete( Employee,key ); end; '3': begin { LIST MODE } LIST; end END{CASE} END{IF}; MENU; INPUT( 'COMMAND: ', answer ); Command := toupper( answer[1] ); END{WHILE Command <> '9'} END{of PROGRAM BTREE}. .