J. P. Tremblay, P. G. Sorenson and D. M. Manegre - Instructor's Solutions Manual To Accompany An Introduction To Data Structures With Applications-McGraw Hill (1984)
J. P. Tremblay, P. G. Sorenson and D. M. Manegre - Instructor's Solutions Manual To Accompany An Introduction To Data Structures With Applications-McGraw Hill (1984)
TO ACCOMPANY
AN INTRODUCTION
TO DATA STRUCTURES
‘WITH APPLICATIONS
— SECOND EDITION
JEAN-PAUL TREMBLAY
PAUL G. SORENSON
and
DONNA M. MANEGRE
Department of Computational Science
University of Saskatchewan, Saskatoon
anada
0-07-065165-5
The authors would like to thank Michael Doritich for assisting in providing
solutions to many of the problems, and Shane McDonald for assisting in the
formatting of the manual. We also wish to thank Brent Clark for helping to proof
read sections of the manual.
CHAPTER 1
2 0010
3 C011
4 0100
5 0101
6 0116
7 0111
8 1000
9 1001
10 1010
11 1011
12 1100
The length of the code is greater than the value calculated in proble
m 1. The
value calculated should be less than the length of the code since all
possible
combinations of the code are not used, and the entropy measure, H,
is a bound
on the minimum average code length.
t=1
3) ROLLED AMOUNT VARIABLE LENGTH CODE
2 00101
3 1000
4 000
5 011
6 110
7 111
8 161
9 010
10 001
11 0011
12 00100
1 1 10 101
Z 2 11 102
3 10 12 110
4 11 13 111
5 12 14 112
6 20 15 120
7 21 16 121
8 22 17 u22
9 100
2) INTEGER BASE9 INTEGER BASE9
1 1 10 11
2 2 11 12
3 3 12 13
4 4 13 14
5 5 14 15
6 6 15 16
i 7 16 17
8 8 Lia 18
9 10
Numbers written in base 3 and base 9 are related. If base 3 numbers are
grouped in groups of two from the ternary point, and these groups are
converted to their decimal equivalent, then the resulting number is the
equivalent base 9 code from the original base 3 code.
1-3
c) 7-11 = (00111), + 1’s comp((01011),)
= (00111), + (10100),
= (11011), ==4
la) i. 0000000000011011
ii. 0000000000011011
b) i. 1212111011111111
ii. 1111111100006000
c) 1. 1111111111111000
Hi. =.1111111111111001
d) i. 0000000060000111
ii. 0000000000000111
e) i. 0000000000101100
ii. 0000000000101100
2a) 001001111100
b) .0010010101101101
——
ES en
c) O1NJ1103
d) 01141100
~~
e) 010001001100
1-4
EXERCISES SECTION 1-4.5 PAGE 56
1) function convbit(ch:char):bitstring;
var index,value,i,j,rem:integer;
bitrep:bitstring;
begin
{ case statement to determine decimal equiv of code }
case ch of
bal tb! tel td! lel Mtg! th! fil: begin
index := ord(ch) — ord(‘a‘);
value := 129 + index
end;
km!
a!o!,'p! ql /r!: begin
index := ord(ch) — ord('j’);
value := 145 + index
end;
Ish 1th tal ty! tw! bx! ty! tal: begin
index := ord(ch) — ord('s‘);
value := 162 + index
end;
VAN IBIIC!D!
ER! IG! HET: begin
index := ord(ch) — ord('A’‘);
value := 193 + index
end;
yy i PME NGI ORD E TOy eRe begin
1=6
2) procedure conint(val:integer;var equiv:numstring);
var i,digit:integer;
negflag: boolean;
begin
{ initializations }
for i := 1 to 10 do
equiv[i] :=' ';
{ check for value of zero }
if val = 0
then equiv[10] := ‘0!
else begin
{ check for negative value }
if val < 0
then begin
val := -val;
negflag := true
end
else negfiag := false;
{ convert to char rep }
Lisa 10:
while {val > 0) do
begin
digit := val mod 10;
equiv|i] := chr(digit + ord('0’));
val := val div 10;
i:s=i-1
end;
{ add negative sign if necessary }
if negflag
then equiv{i] := /—
end
{ return }
end;
17
CHAPTER 2
=> 'EXA#!oa!MEXAM! by P,
=> 'EXA#E'a'MXAM! by P,
=> 'EXA#EX!’a!MAM! by P,
=> 'EXA#EXA!a!MM! by P,
=> 'EXA#EXA! by Ps
=> 'EX#!a! AEXA’ by P,
=> 'EX#E' a! AXA! by P;
=> 'EX#EX'a!' AA! by P,
= 'EX#EX! by Pe
=> 'E#!a!XEX! by P;
=> 'E#E! a!XX! by P,
=> 'E#E! by P,
== al EE’ by Py
—— eu by Ps
=> 'p! by Ps
=> 'NO#!a'TGO!' by P,
=> 'NO#G'a'TO' by P,
=> 'NO#Gte by Ps
=> 'N#!/a!OG!la by P,
=> 'N#’aa by Ps
=> 'Nb/aa by Ps
== Nae by Pe
=> aa by Pe
=> 'ca by P;
251
=> a , by Pe
=> 'c! by Pz ;
=> alabc! by P;
=> 'ala'bc! by Po
=> 'abla'c! by Po
=> 'abcla by Po
=> 'abla'c! pc! by Ps
=> 'abla'cc! by Ps
=>. ‘a'a'b'p bec’ by Ps
== ‘alatbe’sbe’ by FP,
=> 'ala'bee! pb! by Ps
=> 'ala'becb! by Ps
=> oa Pabech’” . by Ps
=> alab’flacch’~ by P,
=> alabc! flacb’ by Ps
=> alabcc! flab! by P4
=> alabccb!fla' by Py
=> a'abccbal by Ps
=> 'abccba’ by Pe
MA: DIFFERENCE(1,- ¢ V)
Pe 44]! URS
Pe: t _s A
to
The approach involves taking the first character in the string and moving it
If a
the end of the string and matching it with the previous end character.
whole
match is achieved, the last two characters are removed and the
matching process begins again. If a match is not achieved, a palindrome does
the
not exist and we halt with output 'b’. If matching is achieved throughout
entire string, then the algorithm halts with output rat
a2
LMA: PALINDROME (x,y « V)
LOOP: A->a
AGAIN: = axy > yax (AGAIN)
xax + A (LOOP)
Kae (OUTB)
ax + a (OUTB)
a—'al.
OUTB: xa>a _ (OUTB)
ax—+a (OUTB)
a 'b!.
The basic strategy is to take elements of x and move them individually (via
mark symbols) over to corresponding elements of y and check to see if x; = y;
for each 1; i = 1 to length of x. If a match fails, then the element-by-element
matching process must be reinitiated with the substring of y consisting of
Y2, Ya, ---» Ym Where m is the length of the complete string y. This matching
process continues for all such substrings of y. If the process fails, then the
roles of x and y are reversed and the matching process is reinitiated.
2-3
BoA
ax + xay (MARK)
BAD: a> aa
GOOD: BoA
ies
pt A
LOOP3: xa->a (LOOP3)
LOOP4: ax—> a (LOOP4)
FINAL: a+ '#! (FINAL)
As A,
INIT: a>
B— Bp (START)
LMA: DIVIDE
P;: [1 /al
Py»: al — la (Pa)
Ps: a—+ B (P;)
Py jo] (Po)
Ps: a—+>A
Pe: fA
Pz: I-A (P7)
P3: Bol (Ps)
Consider the example 7/2 > 1111111/11
1111111/a11 by P,;
1111111/lal by P»
111111/lo1 by P,
1111li/lle by P»
lll11/lla by Py
11111/118 by Ps
lllll/all6 by Py
111l1/lalB by Py
1111/1a1f by P,
l111/lloB by Pp
111/1lap by P,
111/116 by Ps
111/a11p6 iby P,
111/1a1f88 by P,
11/1188 by P;
11/l1a66 by Po
1/11ahp by P,
1/11666 by Ps
1/a11666 by P;
| 1/1a1p88 by Py
2-4
=> /1alp6B by P,
=> /110888 by P,
eR yeisfe. by P;
=> 11/88 by Pe
=> pBp by P;
= lil by Ps
2-5
RM_RIGHT: by > B (RM_RIGHT)
FINAL_OUT: Bond
aos.
{ Function find returns true if the string, pattern, is found anywhere in the
subject string from the cursor character to the end of the subject string. If a
match occurs, matchstr is set to the string beginning with the cursor character
and including all characters to the left of the first character of the pattern
matched. If pattern is found starting with the cursor character, matchstr is
set to the empty string. If replaceflag is set, then all characters starting from
the cursor character up to the right-most character of the matched substring
are replaced by replacestr. }
var temp:string;
integer;
result:boolean;
begin
{ check if pattern fits in bounds of subject string }
if cursor > length(subject)
then result := false
else begin
{ search for pattern match }
sub(subject,cursor,length(subject),temp);
i := index(temp,pattern);
ifi=0
then result := false
else begin
2-6
{ set matchstr and replace }
sub(subject,cursor,i-1,matchstr);
if replaceflag
then begin
psdsub(subject,cursor,length(pattern)+i-1,
replacestr);
cursor := cursor+length(replacestr)
end
else cursor :== cursor+i+length(pattern)-1;
result := true
end
end;
find := result
end; { find }
2-7]
Algorithm TRIM. Given a subject string, SUBJECT, this algorithm trims
off all trailing blanks.
Function BREAK(SUBJECT,PATTERN,CURSOR,MATCHSTR,
REPLACE _FLAG,REPLACE_STR). Given the six pattern matching
parameters, this function scans the subject string on a character by character
basis, starting at the given cursor position and proceeding to the first instance
of a character which is also a character in the pattern string. FOUND is a
boolean variable indicating whether or not a match occurred. I is an integer
variable denoting the position of the match.
2-8
5) procedure delete(var str:string;list:string);
{ All occurrences of each character contained in list are deleted from str. }
var i:integer;
temp,half1,half2:string;
begin
{ initializations }
e—s2°
{ delete bounded characters }
while (i < length(str)) do
begin
sub(str,i,1,temp);
if index(list,temp) <> 0
then begin
sub(str, 1,i-1,half1);
sub(str,i+1,length(str),half2);
concat(half1,half2,str)
end
else i :=i+1
end;
{ delete leading character }
if length(str) <> 0
then begin
sub(str,1,1,temp);
if index(list,temp) <> 0
then sub(str,2,length(str),str)
end;
{ delete trailing character }
if length(str) <> 0
then begin
sub(str,length(str),1,temp);
if index(list,temp) <> 0
then sub(str,1,length(str)-1,str)
end
end; { delete }
6) function verify(str,pat:string):integer;
{ This function returns the position of the first character in str not present in
pat. It is called by the test function below. }
aoe
var i:integer;
next:string;
begin
{ initializations }
ies}
next([1] := str[i];
next([2] := ‘|’;
{ find first char in str not in pat }
while (index(pat,next) <> 0) and (i <= length(str)) do
begin
i:=1+ 1; ‘
next([1] := str[i]
end;
{ check if all chars in str are in pat }
ifi > length(str)
then verify := 0
else verify :=1
end; {verify }
(EBB ROBES EEE BROS IEE OBESE SSEEESE EE IS AGATA AIA AIAAA }
function test(sentence:string):boolean;
var i:integer;
result:boolean;
begin
{ is ‘the’ the first word? }
i := index(sentence,'The |’);
if (i = 0) or (i <> verify(sentence,’ |'))
then result := false
else begin
{ does possessive phrase and ‘possession’ appear? }
sub(sentence,i + 3,length(sentence),sentence);
i := index(sentence,’ belongs to the|’);
if (i = 0) or (i = verify(sentence,’ |'))
then result := false
else begin
{ does ‘possessor! appear? }
sub(sentence,i+14,length(sentence),sentence);
ae 10
i := verify(sentence,' |');
if i = 0
then result := false
else result := true
end
end;
test := result
end; { test }
program analyze(input,output);
{ This program analyzes text from a data file, giving statistics on the number
of sentences, the average number of words per sentence, and the average
number of character per word. } ;
var numwords,numchars,numsents:integer;
avgwords,avgchars:real;
line:string;
i:integer;
fini:boolean;
{ This procedure reads one line of input text, and places it into the parameter
line. }
var i,j:integer;
begin
{ read one line of input text }
i:== 1;
while (not eoln) and (i < 81) do
begin
read(line[i]);
i1:=i+1
end;
readIn;
{ set delimiter }
line[i] := ‘|!;
{ pad with blanks }
for } := 1+ 1 to linesize do
line[j] :=''
end; { getline }
Saati al aaa eae |
#include 'length.i’;
Sahai lacltdlaediadechteticheechnlatededidecettiaeeh |
begin
{ initializations }
fini := false;
while (not fini) do
begin
{ read one line of text }
getline(line);
{ find first non-blank character }
eo Fe
while line|i] = '' do
1:= i+ 1;
{ process each character in line } .
while (i <= length(line)) and (not fini) do
begin
{ check for end of sentence }
if line[i] = /.!
then begin
numwords := numwords + 1;
numsents := numsents + 1;
i:= 1+ 3;
{ check for end of input }
ifi <= length(line)
then ff line[i] = '/'
then fini := true
end
else { check for end of word }
if line[i] =! !
then begin
numwords := numwords + 1;
ie bt
end
else { check for invalid characters }
= '~’))
if ((line[i] = ',’) or (line[i] = ';’) or (line[i]
then i:=i+1
else { must be valid character }
begin
numchars := numchars + 1;
Zt?
{ check for end of last word of line }
ifi = length(line)
then numwords := numwords + 1;
i:=i+1
end
end
end;
{ output results }
avgchars := numchars/numwords;
avgwords := numwords/numsents;
writeln;
writeln;
writeln(/ NUMBER OF SENTENCES: /:25,numsents:5);
writeln(/ AVERAGE WORDS/SENTENCE ':25,avgwords:5:2);
:
writeln(' AVERAGE CHARS/WORD: ':25,avgchars:5:2);
end.
1) The language generated is L = {b’a*— € |a,b € V and €is the empty string.}
2a) <nNOI> = <odd digit> | <integer> <odd digit>
<integer> = <digit> | <digit> <integer>
<digit> = <odd digit> ]0|2|4|6|8
<odd digit> :=1|3|5|7|9
<nNEI> == <evenlead> | <lead> <even integer>
<even integer> ::= <evenlead> |0| <digit> <even integer>
<digit> == <lead> |0
<lead> == <evenlead> |1|3|5|7]9
<evenlead> n= 2|446/8
<E> :=b
<E> :=a<E>a
<E> :=b
<b ere ee
<B> Pek
<name> == <alpha> | <alpha> [ <alphanumeric> |°
<alpha> c= ABYC at lag
<alphanumeric> ::= <alpha> |0|1i]2|...|/9| #|$
=—>i*it+i
6a) 7 - = 3
iI
<digit> <op 1>
| <digit> <op 1>
| <digit>
<DDC expr>
<DDC expr>
OR:
7
|
=
<op 1>
6
:
=
|
<op 1>
i
3
|
<DDC expr> <DDC expr> <DDC expr>
<DDC expr>
Bene eee
iy Rey
< expression > <term>
<term> * <factor>
<factor> * <factor>
<factor> * (<expression>)
<factor> * (<expression> -++ <term>)
<factor> * (<term> + <term>)
<factor> * (<factor> + <term>)
VUbddddy
<factor> * (<factor> + <factor>)
I > i¥*(iti)
<expression> => <expression> + <term>
=> <term> + <term>
=> <term> * <factor> + <term>
=> <factor> * <factor> + <term>
=> <factor> * <factor> + <factor>
2715
7a) <string> := <A>b <A>
<A> == ala<A>
b) <string> u= <A> <B> <A>
<B><A> = bal <B> <B> <A>‘a
<A><B> :=ab|a<A> <B> <B>
<B> == Dp
la) word i
S i R I
word i+ 1
N G
X'D5! X'C7!
b) word i |
length field S T
length = 6 X!E2! ES
2=16
wordi+ 1
R I N G
length = 6 address = 26
S - R I N G
| string space
b) No, such assignments cannot be handled using the boundary marker method.
Suppose C + ‘EXAMPLE’ and then S «+ SUB(C,3,2). The result would be
Coe ae |
s {+—
In addition to assigning S the value ‘AM’, the side-effect of changing the value
of C to ‘E’ would occur. With the descriptor method, no such side-effects
would occur.
3) A garbage collection agency would make efficient use of memory; however, it
is gained at the expense of additional processing time. Therefore, the
feasibility is determined by the application. Generally, memory is a scarce
resource so garbage collection is warranted.
Not all of the spuce pointed at by the vector of ‘‘old’”’ descriptors is
necessarily garbage; some active descriptors may point within a string
identified by an “‘old’’ descriptor. This means garbage is recognized as the
space pointed at by the “‘old’’ descriptors, and not by any of the descriptors in
use.
One method for managing the garbage collection agency is to maintain
vectors (ordered by address) of the “old” descriptors and descriptors in use.
Redundant ‘‘old” descriptors could be removed and adjacent free spaces could
be merged to reduce the size of the vector. When memory is requested, a
search is made of the ‘‘old’’ descriptor vector for a chunk of memory large
enough to satisfy the request. Recall that a check must be made to be sure
that no space within the chunk is pointed at by a regular descriptor vector.
If a request is filled by re-using ‘‘old” space then a new descriptor must
be added to the regular descriptor list and the ‘‘old” descriptor must be
modified or removed.
1) Procedure CENTER(INPUT_LINE,LMARGIN,RMARGIN).
the character string, INPUT_LINE, and LMARGIN and RMARGIN, integers
Given
denoting the positions of the left margin and right margin characters
respectively, the text is centered within the bounds, and printed out.
LEADBL is an integer indicating the number of leading blanks on the line.
1. [Initializations]
FOUND + false
Lit
2. [Search for PATTERN]
Repeat while -FOUND and I < AVAIL
If INDEX(LINE[I], PATTERN) + 0
then FOUND + true
else I+I+1
4, |Check if pattern found]
if -FOUND
then Write(/PATTERN NOT FOUND’) -
Retarn :
4, (Make substitution]
START — INDEX(LINE[I PATTERN)
SUB(LINE[] START ,LENGTH(PATTERN)) — NEW
5. [Finished]
Return
Var posinteger;
next delim Jine numeric alpha alphanum ,reserved-string,
comment, test: boolean;
procedure revdsym;
Var ‘integer;
begin 7
{ determine which reserved symbol }
>a i c= index{reserved next);
{ separate into 1 and 2 character symbols }
if(line|pos + 1] = '*’) and (i = 3) { exponentiation }
then begin
2-20
writeln;
writeln(/ TOKEN = ':8,'8 *#':5);
pos := pos + l
end
else if (line[pos + 1] = '=') and (i = 7) { assignment }
then begin
writeln;
writeln(/ TOKEN = ':8,'7 :=':5);
pos := pos + l
end
else ifi = 8 { opening comment delimiter }
then comment := true
else if i = 9 { closing comment delimiter }
then writeln(’/***ERROR: EXTRA DELIMITER##*+’)
else ifi <> 10 { all symbols except ';’ }
then begin
ifi<=4
then write(/ TOKEN = ':8,((i+5)div 2):1,
1 1.9)
else write(/ TOKEN = ':8,i:1,' ':2);
writeln(next:1)
end
end; { rsvdsym }
{ This function passes the next non-blank character in the input stream
through the parameter ch, returning true if an eof has been reached. }
var i,j:integer;
result: boolean;
. begin
{ check for processing of comment }
if (comment)
then if (index(line,delim) <> 0)
then begin
comment := false;
pos := index(line,delim) + 1;
while (pos <= 80) and (line[pos] = ' ') do
pos := pos + 1
end
else comment := true {dummy assignment}
Zoe
else begin
{ find next non-blank character }
pos := pos + 1;
ifpos <> 81.
then while (pos <= 80) and (line[pos] =‘ ') do
pos := pos + l
end;
{ loop to read in new lines until non-blank char or
comment delimiter found }
while ((pos = 81) or (comment)) and (not eof) do
begin
{ read new line }
ele
while (i <= 80) and (not eoln) do
begin
read(line[i]);
l= p+ 1
end;
- readin;
{ pad line with blanks }
for j := ito 80 do
line[j] :=' ';
line[81] := '|';
{ print data of line }
writeln;
writeln;
writeln(!**LINE** ':9 line :80);
writeln;
{ check if comment delimiter is present }
if (comment)
then if (index(line,delim) <> 0)
then begin
comment := false;
pos := index(line,delim) + 1;
while (pos <= 80) and (line[pos] = ' ‘) do
pos := pos + 1
end
else comment := true {dummy assignment}
else begin
{ determine position of first non-blank character }
pos := 1;
while (pos <= 80) and (line{pos] = ' ') do
pos := pos + l
end
end;
2522
{ check for end of data file }
if (eof) and ((pos = 81) or (comment))
then begin
result := false;
if comment
then writeln(!*##£RROR: NO DELIMITER***")
end
else begin
result := true;
ch{1] := line[pos]
end;
nonblank := result
end; { nonblank }
DEBE EEE OE BOAO EOE EAE SE EASES gE ESE BE Gn gE }
procedure scan(valid:string;code:char);
var temp:string;
begin
{ initializations }
temp := ! |;
{ write code number }
write(/ TOKEN = ':8,code:1,' !/:2);
{ pass through all valid characters }
temp[1] := line[pos];
while (index(valid,temp)<>0) and (pos <= 80) do
begin
write(line[{pos]:1);
pos := pos + 1;
if pos <> 81
then temp[1] := line[pos]
end;
if code = '2!
then writeln(' ');
{ adjust pos to point to last valid character }
pos := pos — l
end; { scan }
2-23
begin
{ initializations }
pos := 80;
comment := false;
next := ! |';
numeric := '0123456789|';
alpha := ‘abcdefghijklmnopqrstuvwxyz|';
alphanum :=='0123456789abcdefghijklmnopqrstuvwxyz|';
reserved := '+--*/():{}5|';
delim := '}|';
{ get first nonblank symbol }
test := nonblank(next);
{ process chars until end of file detected }
while (test) do
begin
if index(numeric,next) <> 0 { check for numeric representation }
then scan(numeric,’2’) :
else if index(alpha,next) <> 0 { check for identifier representation }
then scan(alphanum,'1’)
else if index(reserved,next) <> 0 { check for operator }
then rsvdsym
else begin
{ invalid symbol detected }
writeln;
writeln('#*#*ERROR: BAD SYMBOL /:25,next:1,
' DETECTED IN COLUMN (:20,pos:3);
end;
{ get next nonblank character }
test := nonblank(next)
end;
writeln;
writeln;
writeln(/END OF FILE DETECTED’); -
end.
2<24
EXERCISES SECTION 2-5.3 PAGE 143
1. [Initializations]
LOC + 0
I+ 1
2. [Linear search]
Repeat while I < LASTWORD and LOC 4 0
_If WORD = ORD_WORDII]
then LOC +]
else I+I+1
3. [Finished]
Return(LOC)
2-26
5. [Separate into and/or relations]
If SUB(COMMAND, I+ 1,3) 23 AND!
then Call INTERP(SUB(COMMAND, I+5),OUT2)
Repeat for I = 1, 2, .... LAST_TITLE
If OUTI[I] and OUT2II]
then FOUNDII] + true
else FOUNDII] < false
else Call INTERP(SUB(COMMAND, I+4),OUT2)
Repeat for I = 1, 2, ..., LAST_TITLE
If OUT}{I] or OUT[I]
then FOUNDII] + true
else FOUND|I] + false
6. [Finished]
Return
1. [Initializations]
LOC + LAST_KEY + 1
I+ 1
2. [Linear search]
Repeat while I < LAST_KEY
If WORD > KEYWORD{]]
then LOC +I
I-—I+1
3. [Insert keyword in appropriate location if necessary|
If WORD 4 KEYWORD[LOC]
then Repeat for J = LAST_KEY + 1, LAST_KEY + 2, ...,. LOC + 1
KEYWORD|J] + KEYWORD{J — 1]
T_INDEX[J] — T_INDEX{J — 1]
LAST_KEY + LAST_KEY + 1
KEYWORD|LOC] + WORD
4. [Finished]
Return(LOC)
CHAPTER 3
When b, = 0, be = 1, u, = n- 1, and up = 6
loc(Ay) = Lo + (j - 1) * M- 1-14 1) + (i- 0)
=L)+(j-1)*(n-1) +i
4) loc(X[i,j,k]) = Lo + 6 * (i-1)+2*(j-1)+k+41
=) am n bytes m bytes
3-1
3) 1) GRAINS
2 WHEAT
3 PROD (integer)
3 PRICE (real)
2 BARLEY
3 PROD (integer)
3 PRICE (real)
2 OATS
3 PROD (integer)
3 PRICE (real)
2 RAPESEED
3 PROD (integer)
3 PRICE (real)
2 FLAX
3 PROD (integer)
3 PRICE (real)
4) 1 REQUEST
2BOOK_TITLE (string - 80 chars)
2 PRICE (real)
2 WHO(20)
3 NAME (string - 40 chars)
3 ADDRESS (string - 160 chars)
are
smoking: boolean;
window: boolean;
seatclass: class;
price: real
end;
b) const namelen = 30;
addrien = 80;
contracts = (A,B,C,D);
oo
month: 1..12;
year: integer
end;
license = record
name: packed array[1..namelen] of char;
address: packed array[1..addrlen] of char;
licnum: integer;
liccode: integer;
birth: date;
expiry: date;
coloreyes: packed array[1..strlen| of char;
height: measure
end;
e) const namelen = 30;
6) 1 ALCOHOLIC_BEV
2 WINE
3 CHAMPAGNE(10)
3 SHERRY(5)
3 RED(20)
3 WHITE(10)
3 SPARKLING(5)
2 WHISKEY
3 RYE(6)
3 SCOTCH(6)
3 BOURBON(3)
2 RUM(10)
2 COGNAC(5)
2 GIN(7)
2 VODKA(5)
3-4
EXERCISES SECTION 3-4 PAGE 176
3-2
BIJ] — BiJ] + 1
else (try to move downward)
FOUND + false
Repeat for J = I-1, 1-2, ..., 1 while >FOUND
If T[J] < BlJ+1]
then FOUND + true
SAVE + J
If FOUND
then Repeat for J = SAVE, SAVE-+1., ..., I
Repeat for M = B[J], B[J]+1, ..., T[J]
S[M-1] — S|M]
BJ] — Bld] -1
T(J] + T[J] - 1
else (entire stack structure is full)
Write(/STACK OVERFLOW’)
Return
2. [Increment TOP]
Ti] — Tif} +1
3. [Insert element]
S[T[]] -— X
4. [Finished]
Return
Function POPI(S,I). This function removes the top element from a stack
L
3-6
1. [Only 1 value left?|
If LOWBOUND = HIGHBOUND
then Write(/MEDLAN VALUE IS ! SCORE[LOWBOUND)])
Return
2. [Exchange minimum value]
TEMP <— MIN(LOWBOUND,HIGHBOUND)
I ~ LOWBOUND
Repeat while SCORE[I] +4 TEMP
era
SCORE[I] <—> SCORE[LOWBOUND]
3. [Exchange maximum value]
TEMP «+ MAX(LOWBOUND,HIGHBOUND)
I + HIGHBOUND
Repeat while SCORE|I] a TEMP
be Ta
SCORE[I| <-> SCORE/HIGHBOUND]
4. [Invoke recursive call]
Call MEDIAN(LOWBOUND + 1, HIGHBOUND - 1)
“ [Finished]
Return
t
TOP
Enter Step 4: Call MEDIAN Pea 12 67 31 26 88
level 2 (LOWBOUND, Can
ia ee
(1st HIGHBOUND) Step 5
recursive
call) T
TOP
Enter Output: MEDIAN VALUE 12 26 31 67 88
level 3 IS 21 (See
|Armes lia
(2nd Step 5|Step 5
recursive
call) t
TOP
oh
Return to Step 5: Return o 12oo 26
« 31 67i 88
level 2
E Main | Step 5
t
DOP.
in to
Return Step 5: Return pj fT 12 26 31 67 88
Maio| ___|
TOP
Return
ae to Step 5: Return 12 26 31 67 88
1. [Initializations]
M + S[1]
N1 + N2+ N3+ 0
oe [Isolate subsets]
Repeat for CTR = 1, 2, 3, ..., N
If SICTR] < M
then Ni«+ Ni1+1
S1[N1] + S[CTR]
else If S[CTR] > M
then N3+ N3+ 1
S3[N3] + S[CTR]
3-8
else N2 + N2+1
S2[NQ] — S[CTR]
3. [Make recursive call]
IitK < NI
then Return(FIND(K,S1,N1))
else IfK < N1 + N2
then Return(M)
else Return(FIND(K-N1-N2,S3,N3)}
t
TOP
Return to Step 3: Return(FIND
level 1 (K1,S2,N1)) cht aaah oe
arséege te
Main Pat Tey
t
TOP
Return to Step 3: Return(FIND
main (K-N1-N2,$3,N3))
eee ee
3a) Procedure MAXMIN(S,N,START,MAX,MIN). Given a vector S with
N elements, this procedure simultaneously finds the largest and smallest
elements of the vector.
3. [Split S]
M+[N/2]
4. [Process Ist half]
N«-M
ADDRESS + Step 5
Go to Step 1
5. [Receive results of process]
Call MAXMIN(S,M,START,MAX1,MIN1)
6. [Process 2nd half
TEMPREC + POP(A,TOP) (restore original environment)
PUSH(A,TOP,TEMPREC) (save activation record)
M+|N/2]
N+N-M
START «+ START + M
ADDRESS + Step 7
Go to Step 1
7. [Receive results of process]
Call MAXMIN(S,N-M,START+M,MAX2,MIN2)
8. [Determine results] ,
If MAX1 > MAX2
then MAX + MAXI
else MAX «+ MAX2
If MIN1 < MIN2
then MIN «+ MINI
else MIN «— MIN2
ad [Restore activation record]
TEMPREC + POP(A,TOP)
Go To ADDRESS
1
21 or 86
Pisce
Gael SeBone a
t
TOP
BhiZ
Return to Step 5: Call MAXMIN(S,M,
level 1 START,MAX1,MIN1)
PUSH(A,TOP, feves72
|ovse72 | |
faseas [is.e9 1[I
Enter Step 1:
TEMPREC)
level 2
(1st ceees
recursive
call)
t
TOP
Enter Step 1: PUSH(A,TOP,
level 3 TEMPREC) 13 9951 | 139951 | 139951
(2nd Owen Pino sl 2
recursive
call)
genre eae
Ls
Mai
ane
Return to Step 7: Call MAXMIN(S,N-M, 21 86 72 21 86 72
level 2 START+M,MAX2,MIN2) 13 99 51 13 99 51
1 PaaS
cae
4a) Function BC(N,K). This recursive function finds the Kth binomial
coefficient of the polynomial of degree N given by (A + Bye
Enter BC(2,2
level 1
(main call)
Enter N=K
level 2 Return(1)
(1st recursive
call)
OP
Return to Return(1 + 2)
level 1
t
TOP
Return to Return(3) 3
main
3715
6) Function TRIM(TEXT). This recursive function removes leading and
trailing blanks from the input string, TEXT.
1. [Recursive call]
If TRUNC(NUMBER/RADIX) > 0
then ANSWER «+ CONVERT(TRUNC(NUMBER/RADIX),RADIX)
else ANSWER + "
2. [Convert integer to character]
ANSWER «+ ANSWER © SUB('0123456789', MOD(NUMBER, RADIX)
ois)
3. [Finished]
Return(ANS WER) '
b)
Level Number Description Stack Contents
b)
Level Number Description
t
TOP
|pPy° eyeo
y-
Return to Step 2: STR + '10' 0 /5!
level 2 Step 3: Return(STR)
1. [Base condition]
If N=0
then Return('.’)
De [Recursive cal]]
RESULT — CONVERT(FRACTION,BASE,N-1)
3. [Perform computation]
TEMP + FRACTION «+ FRACTION * BASE
FRACTION + MOD(FRACTION,1)
TEMP ~— TEMP - FRACTION
S216
4. [Convert digit to character]
RESULT «+ RESULT © SUB('0123456789',TEMP + 1,1)
5. [Return result]
RETURN(RESULT)
var n,x:integer;
DEBE BEE BEBE EEE EAE BEE GEER EEE HDDS SAH BE EEE BE GE #4}
function eval(n,x:integer):integer;
var a,result:integer;
begin
{ apply recursive definition }
ifn = 0
then begin
readIn(a);
eval :=a
end
else begin
read(a);
result := (x * eval{n—1,x)) + a;
eval := result
end
end;
(EHH R EER EEE EEE EEE BEEBE OEE EE EEE CECE CEE AEE 4 44}
begin
{ engage loop to process all data }
while not eof do
begin
read(n,x);
ifn <0
then writeln(/ERROR: NEGATIVE VALUE FOR POLYNOMIAL!)
else writeln(/POLY EVALUATED AT /:18,x:2,! = ':3,eval(n,x):4)
end
end.
POLY EVALUATED AT 2= 27
var i:integer;
next,expression:string;
#include 'length.i';
#include 'index.i’;
#include 'sub.i';
#include 'verify.i';
#include 'getline.i’;
GER EBB EACH ORES SES SABE OBESE EEE AAAS AAAI TATE IA AAT }
function nextsym:string;
{ This function returns the next unexamined nonblank character from the
global input string of symbols. When all characters have been examined, a
blank is returned. }
var temp:string;
result:string;
begin
{ initializations }
result[2] := '|!;
{ check for end of input string }
ifi = length(expression)
then result[1] :=‘''
else begin
{ pass over blanks }
sub(expression,i + 1,length(expression),temp);
{ check for end of input string }
if verify(temp,’ |’) = 0
then result[1] :=‘ ’
else begin
5720
{ isolate next symbol }
i := i + verify(temp,’ |’);
result({1] := expression{i]
end
end;
nextsyi := result
end;
function eval:boolean;
{ This function evaluates the infix expression, returning true if valid; false
otherwise. }
var next:string;
begin
{ remove next symbol }
next := nextsym;
{ evaluate expression }
if next/1] = ‘(' ;
then if (not eval) or (index('+—*/|' nextsym)=0) or (not eval)
then eval := false
else begin
next := nextsym;
if next(1] =‘)
then eval := true
else eval := false;
end
else if index('ABCDEF GHI JKLMNOPQRSTUV WXY 20123456789" next) =
then eval := false
else eval := true
end;
begin
{ engage loop to process all data }
while not eof do
begin
{ read expression }
getline(expression);
write(expression:length(expression),’ ':2);
Stal
{ evaluate validity of expression }
1 :=.0;
if (eval)
then begin
next := nextsym;
if next(1] = //
then writeln(' VALID EXPRESSION’
:18)
else writeln('INVALID EXPRESSION’
:20)
end
else writeln(/ INVALID EXPRESSION’)
end
end.
var n:integer;
a,e:real;
EBB ABBE EEE E EAE E CECB ABOBBIE CS ACE CEES CECE EEE KE ++}
function root(n:integer;a,e:real):real;
begin
{ apply recursive definition }
if abs(a
* a—n) <e
then root := a
else root := root(n,(a * a + n)/(2 * a),e)
end;
;
begin
{ engage loop to process all data }
while not eof do
begin
{ read data }
B22
readIn(n,a,e);
{ check for valid data }
if (n < 0) or (a< 0) or (e < 0)
then writeln(/ERROR IN DATA! :15,n:3,a:3:3,e:3:3)
else writeln('SQ ROOT WITHIN /:15,e:3:3,’ = ':3,root(n,a,e):3:3)
end
end.
var data:string;
FEBSBEEE ESSE EEASES ESSA EAS OBOE IEEEAE FOS ASABE EE Ea}
#include 'length.i’;
#include ‘sub.i’;
#include ‘concat.i';
#include 'getline.i';
GABE BEERS B EGE EES EEE ESSE IEEE IARI I TATE AAAA AIS]
procedure perm(sofar,rest:string);
var |,i:integer;
templ,temp2,temp3,temp4:string;
begin
{ check for string of one character }
1 := length(rest);
ifl!=—1
then begin
concat(sofar,rest,temp1);
writeln(temp1:length(temp
1))
end
3723
else begin
{ recursive calls }
sub(rest,1,1,temp 1);
concat(sofar,temp1,temp2);
sub(rest,2,length(rest),temp1);
perm(temp2,temp1);
for i := 2to!—1do
begin
sub(rest,i,1,temp!);
concat(sofar,temp1,temp2);
sub(rest,1,i — 1,temp3);
sub(rest,i + 1,length(rest), temp4);
concat(temp3,temp4,temp
1);
perm(temp2,temp1)
end;
sub(rest,1,1,temp1);
concai(sofar,temp1l,temp2);
sub(rest,1,1- 1,temp1);
perm(temp2,temp1)
end
end;
begin
{ engage loop to process all data }
while not eof do
begin
getline(data);
writeln(/ PERMUTATIONS OF: ‘ data:length(data));
perm(' |data)
end
end.
3-24
2341
2413
2431
3124
3142
3214
3241
3412
3421
4123
4132
4213
4231
4312
4321
var int:integer;
function q(m,n:integer):integer;
var temp:integer;
begin
{ apply recursive definition }
if (m= 1) or (n = 1)
then temp := 1
else ifm <n
then temp := q(m,m)
else if m =n
then temp := 1 + q(m,m-1)
else temp := q(m,n-1) + q(m-n,n);
{ return }
q := temp
end;
3525
Saladin lahacidediedaclaclatiedi diclei dada: Iaiatadacacetiedaddiadiedancadedaedtdedcecttecteietndieiniicaiedeiniaiaiaiad |
begin
{ process all data }
while not eof do
begin
readIn(int);
writeln(q(int,int),’ PARTITIONS FOR', int)
end
end.
3 PARTITIONS FOR 3
5 PARTITIONS FOR. 4
7 - PARTITIONS FOR ..-9
11 PARTITIONS FOR 6
1) program rpolish(input,output);
var expression:string;
next:char;
isinteger;
JAAS ESSEC HEE HSA EA ESA EGE Eda bee tee tt}
#include 'length.i’;
#-include 'index.i';
#include 'verify.i';
#include 'getline.i’;
GABE EEE EEE EEE EE IEEEEE EAE AAAI REAR EATS TAS FASTA EASES }
function expr:boolean;
3-26
var temp:string;
begin
ifi <= 6
then expr := false { missing subexpression }
else begin
next :== expression{i]; { get next symbel }
b= 1—
if next =="?
then expr := expr { ignore blanks }
else begin
temp{1] := next;
temp|[2] :-='|';
if index('+—*/|',temp) <> 0
then if (expr) and (expr)
then expr := true
else expr := false
else if index('ABCDEF GHIJKLMNOPQRSTUVW
XYZ0123456789' temp) <> 0
then expr := true
else expr := false
end
end
end;
FEE SRSA EE SSE EEE AEE IIE IIIA EE EE RICEEEE IEEE EES }
begin
{ process al! data }
while not eof do
begin
getline(expression);
write(expression:length(expression));
i := length(expression);
if (expr) and (verify(expression,’ |!) = i + 1)
then writeln(’ VALID EXPRESSION’)
else writeln(' INVALID EXPRESSION’)
end
end.
A+BeC
(A + B) /12
3) PRECEDENCE
SYMBOL INPUT PRECEDENCE STACK PRECEDENCE RANK
FUNCTION f FUNCTION g FUNCTION r
| 1 2 -1
& 3 4 -l
a 6 5 0
8 -l
<,<,>,2,=,4 7
+,- 9 10 -1
*,/ 11 12 =}
9 14 13 0
t 16 15 ay
variables 17 18 1
19 0 :
0 - :
3-28
A| B= C([D 40 ABC=|Do|
A<B&7A(C|6TQ<Q/V) AB<C6QTQV/<|7&
A&B&(AC)=ARZBEAC AB&Cr&
Algorithm PREFIX. Given an input string, INFIX containing an infix
expression which has been padded on the right with ‘)’, this algorithm creates
the equivalent prefix expression. Two string stacks are used: S1, indexed by
TOP1, which contains the operators; and S2, indexed by TOP2, which
contains the intermediate operands. OP contains the current operator being
removed from the operator stack. LEFT and RIGHT contain the left and
right operands of the current operator respectively. Algorithms PUSH, POP,
and NEXTCHAR (as described in the text) are invoked. Precedence functions
are given below.
1. [Initializations]
VALID + true
TOPI1+ 1
Si[TOP]] — '(!
TOP2 + 0
2. [Get first input symbol]
NEXT + NEXTCHAR(INFIX)
3. [Scan expression]
Repeat thru step 4 while (NEXT > '') and VALID
4. [Logical end of expression?
If TORT = G6
then VALID + false
else If (NEXT) = 6 (operand?)
then Call PUSH(S2,TOP2,NEXT)
else Repeat while (f((NEXT) < g(S1[TOP1])) and VALID
If TOP2 <1
then VALID + false
else OP + POP(S1,TOP1)
RIGHT ~ POP(S2,TOP2)
LEFT — POP(S2,TOP2)
Call PUSH(S2,TOP2,OP © LEFT o RIGHT)
If NEXT = '}
then TOP1< TOP1-1
a20
else Call PUSH(S1,TOP1,NEXT)
NEXT + NEXTCHAR(INFIX)
5. [Valid expression?]
If VALID and (TOP1 = 0) and (TOP2 = 1)
then Write(/VALID EXPRESSION’)
else Write(‘INVALID EXPRESSION’)
var polish:string;
s:stack;
top:integer;
CABBIE EEE EES BE EEO SSSA EEE EEE ABE EE EAE EAA ES }
#include ‘length.i';
#include 'getline.i';
#include 'concat.i';
GABE EEE ESSE EE EBSA G ABABA EEE EE EE EEA A AA TAA TIE}
begin |
{ check for stack overflow }
if top >= 100
then writeln(/STACK OVERFLOW’)
else begin
{ increment top and insert x }
top := top + 1;
s[top] := x
end
end;
GER EG OBE HOHSS EOEES OHA B REESE EBA BEASE AAA IAAI }
3-30
function pop(var s:stack;var top:integer):string;
begin
{ check for stack underflow }
if top = 0
then writeln(/STACK UNDERFLOW’)
else begin
{ decrement top and return element }
pop <= s|top];
top := top — l
end
end;
Saadallah adalat |
procedure assemblycode(polish:string);
{ This procedure generates assembly code for the given polish string. For
simplicity, it is assumed that there will be a maximum of nine
temporary holders in order that the built-in chr function may be used. }
var top,i,j:integer;
next,right, left, first,second,third,temp,chari,opcode:string;
begin
{ initializations }
top := 0;
bi "0;
{ scan expression }
for j := 1 to length(polish) do
begin
next[1] := polish{j];
next[2] :=—= ‘';
if (‘A’ <= next[1]) and (next[1] <= 'Z')
then push(s,top,next)
else begin
case next|1] of
‘+! opcode == "ADD: |!
‘1: opcode := 'SUB |};
‘+!: opcode := 'MUL |;
'/': opcode := 'DIV|
end;
right := pop(s,top);
left := pop(s,top);
Bra
concat(/LOD |! left,first);
concat(opcode,
right second);
writeln(first:length(first));
writeln(second:length(second));
1:=i+ 1;
chari[1] := chr(i + ord('0’));
chari{2| := '|!;
concat('T|' ,chari,temp);
concat('STO |!,temp, third);
writeln(third:length(third));
push(s,top,temp)
end
end
end;
FEES E EOE CE ESO BOEE EOE OE SHORES AES OBEOS ESB EB AEH EEE +}
begin
{ initialize stack }
top := 0;
{ engage loop to process all data }
while not eof do
begin
{ read expression }
getline(polish);
writeln;
writeln(polish:length(polish));
{ call proc to generate assembly code }
assembly code(polish)
end
end.
ABCDEF+-—/*+
LOD E
ADD F
SLO Pl
LOD D
SUB T1
STO-T2
LOD C
a9
DIV T2
STO T3
LOD B
MUL T3
STO T4
LOD A
ADD T4
S bOMio
AB+CD/-
LOD A
ADD B
STO Ti
LOD C
DIV D
STO T2
LOD T1
SUB T2
STO T3
6) Algorithm ASSEMBLY_CODE. Given a string, POLISH, as previously
discussed, this algorithm generates assembly language instructions, taking
advantage of the commutativity of operator * and +. #£xThe
COMMUTATIVITY flag is set when applicable to indicate the omission of
redundant code. All other variables are as discussed previously.
1. [Initializations]
TOP +I+0O
COMMUTATIVITY << false
2. [Process all symbols]
Repeat thru step 4 for J = 1, 2, .... LENGTH(POLISH)
3. [Obtain current input symbol]
NEXT + SUB(POLISH,J,1)
4. [Determine type of symbol]
IAG < NEXT and NEXT: < $7?
then Call PUSH(S,TOP,NEXT) (push variable on stack)
else Select case (NEXT)
Case '+!:
OPCODE «+ ‘ADD !
Case pen
OPCODE + ‘SUB!
Case '*!:
OPCODE + MUL !
Case !/':
OPCODE + ‘DIV!
Doe
RIGHT + POP(S,TOP) (unstack two operands)
LEFT — POP(S,TOP)
NEXT =" /"or NEXT =!
then If COMMUTATIVITY
then COMMUTATIVITY + false
Write('STO' © LEFT)
Write((LOD ! © LEFT) (output load instruction)
Write(OPCODE © RIGHT) (output arithmetic instruction)
I-I+1 .
TEMP + 'T! oI
Write(/STO ‘ © TEMP) (output temporary storage)
Call PUSH(S,TOP, TEMP)
else If COMMUTATIVITY
then Write(OPCODE © RIGHT)
else Write(/LOD‘ 0 LEFT)
Write(OPCODE © RIGHT)
COMMUTATIVITY << true
I+I+4+1
TEMP + 'T! 0 I
Call PUSH(S,TOP, TEMP)
5. [Output storage if necessary]
If COMMUTATIVITY
then TEMP «'T’ 0]
Write(/STO! 0 TEMP)
6. [Finished] :
Exit
7) program driver(input,output);
var polish:string;
s:stack;
top:integer;
(EEE EEEEEEEEE EE EEEEEEEEEE OEE EEE AIR IIIT IIE A IA AIA ATES
#include ‘length.i’;
#include 'getline.i’;
#include ‘concat.i';
GE EEEAREA E EERE EE ESSE EEE CEE EEE ASIA ITAA IAAAI IAAF
3-34
procedure push(var s:stack;var top:integer;x:string);
begin
{ check for stack overflow }
if top >= 100
then writeln(/STACK OVERFLOW’)
else begin
{ increment top and insert x }
top := top + 1;
s[top] := x
end
end;
FEBS EESSE SESE IE SEO ESSS ESAS EOE EAE AEB AREA tote }
begin
{ check for stack underflow }
if top = 0
then writeln(/STACK UNDERFLOW’)
else begin
{ decrement top and return element }
pop := s[top];
top := top -1
end
end;
procedure assemblycode(polish:string);
{ This procedure generates assembly code for the given polish string. For
simplicity, it is assumed that there will be a maximum of 9 temporary holders,
in order that the built-in chr function may be used. }
var top,i,j:integer;
next,right,left, first,second, third ,temp,chari,opcode:string;
commutativity :boolean;
begin
{ initializations }
top := 0;
355
p= 0;
commutativity := false;
{ scan expression } )
for j := 1 to length(polish) do.
begin
next[1] := polish{j];
next[2] c= “|;
if ('A’ <= next/1]) and (next[1] <= '2’)
then push(s,top,next)
else begin
case next[1] of
'4!: opcode := ‘ADD |;
!_!. opcode := ‘SUB |;
'x!: opcode := ‘MUL |;
'/': opcode := 'DIV |!
end;
right := pop(s,top);
left := pop(s,top);
if (next{1] = '/') or (next[1] = ‘-')
then begin
if commutativity
then begin
commutativity := false;
concat('STO |’ left, first);
writein(first,length(first))
end;
concat(/LOD |’ left, first);
concat(opcode,right,second);
writeln(first:length(first));
writeln(second:length(second))};
j= 1-1;
chari[1] := chr(i + ord(‘0’));
chari[2] := “|!
concat('T|' ,chari,temp);
concat(/STO |temp,third);
writeln(third:length(third));
push(s,top,temp)
end
else begin
if commutativity
then begin
concat(opcode,
right, first);
writeln(first:length(first))
end
else begin
3-36
concat(/LOD | left, first);
concat(opcode,right,second);
writeln(first:length(first));
writeln(second:length(second));
commutativity := true;
Leslie
end;
chari[1] := chr{i + ord('0’));
chari[2] :==-"|/;
concat(! T|’ chari,temp);
push(s,top,temp);
end
end
end;
if commutativity
then begin
chari[1] := chr(i + ord(’0’));
chari[2] := ‘|’;
concat('T|’ chari,temp);
concat('STO |’ ,temp,third);
writeln(third:length(third))
end
end;
GAB ESSE OEE SESE ESE nOBo EES a abo aaa nSrb Rrarab EEL
begin
{ initialize stack }
top := 0;
{ engage loop to process all data }
while not eof do
begin
{ read expression }
getline(polish);
writeln;
writeln(polish:length(polish));
{ call proc to generate assembly code }
assembly code(polish)
end
end.
3238
BC*¥A+
LOD B
MUL C
ADD A
STO Tl
BC*A+D*
LOD B
MUL C
ADD A
MUL D
Seoul s
9) The following modifications are necessary to generate code for the six
relational operators:
3-38
then
else
In order to generate code for the six relational operators, we have created 6
more machine instructions. Zero denotes false; anything else (usually one)
denotes true.
EQ a If the value in the accumulator equals contents of ‘a’ then the value
of the accumulator is changed to 1; otherwise it is changed to 0.
NEQ a_ If the value in the accumulator is not equal to contents of ‘a’ then
the value in the accumulator is changed to 1; otherwise to 0.
LT 2a If accumulator < ‘a! then ...
GT a If accumulator > ‘a! then ...
LTE a _ If accumulator < ‘a’ then ...
GTE a__siIf accumulator > ‘a! then ...
3-39
11) An unconditional statement, for our restricted language is a simple assignment
statement as previously discussed. The infix expression is translated to reverse
polish and code can be easily generated by algorithm ASSEMBLY_CODE.
Let us now consider a conditional statment. It has the form If.
<condition> then <statement> where the <condition> or the
<statement> can be simple, compound, or arbitrarily complex. This
statement can be translated, (via algorithm REVPOL with minor
modification) to the reverse polish form <suffix form of condition> ? <suffix
form of statement>. As an example, If A<B & C=D | A>B & CSD then
A =At (A+B - 1) would be translated aa AB<CD=&£AB>CDS
& |? ABAB+1-f +. Code generation from this form is solved in
exercise 9 of this section, with the exception of the '? operator. It generates a
conditional branch instruction to a strategically placed table. We demonstrate
this by using our example once more:
LOD A
LTB
evaluate condition SPorrt
LOD C
EQ D
if accumulator = 0 BOZ 0
then branch to labeled
statement
perform statement LOD A
ADD B
1. [Initializations]
EceuQ
Call SCAN(I,NEXT)
2. [Remove identifier, and call function to generate term code]
If IDENT(IDENTIFIER) (call function to isolate identifier)
then If TERM('LOD ') (call function to generate code)
then Write('STO! 0 IDENTIFIER)
3-40
else Write(/INVALID TERM’)
else Write(/INVALID IDENTIFIER’)
3. [Finished]
Exit
Se
1. [Initializations]
Call SCAN(I,NEXT)
2. [Check for identifier]
If IDENT(IDENTIFIER)
then Write(OPCODE © IDENTIFIER)
Return(true)
3. [Check for operator]
If INDEX(!+-*/!, NEXT) = 0
then Return(false)
4, [Determine opcode]
Select Case (NEXT)
Case !-+!:
OPCODE « ‘ADD!
Case {.!*
OPCODE + SUB!
Case ys
OPCODE + ‘MUL '
Case '/!
OPCODE + 'DIV!
5. [Scan to next non-blank character]
Call SCAN(I,NEXT)
6. [Check for terms]
If TERM('LOD ‘)
then If TERM(OPCODE)
then Return(true)
else Return(false)
else Return(false)
1. [Insertion to front?]
If FRONT and F 4 1
then IfF =O
rep iahoe R= I
else F—F-1
3-42
DQ[F] — Y
Return
2. [Insertion to rear?|
If REAR and R 4 N
then IfFf =O
then fi)
else: ER Reral
DQ|R] — Y
Return
3. [Insertion disallowed]
Write(/DEQUE OVERFLOW’)
Return
By calling these algorithms with the appropriate values for the arguments
FRONT and REAR, it is possible to:
i. disallow all insertions/deletions
ii. allow insertions/deletions only at front
iii. allow insertions/deletions only at rear
iv. allow insertions/deletions at either front or rear
3eh3
4) initially
after insert l| ~
after delete I
after delete | I|
after insert ~
qn
—
Procedure REVERSE(F,R,Q,N). Given a queue, Q, front and rear
pointers to its elements, F and R, and N, the size of the vector, this procedure
reverses the order of the elements in the queue. S denotes a stack with its
associated index, TOP.
3-45
FOUND + false
Repeat for J = 1I-1,I-2,..., 1 while AFOUND
If R[J] < F[J + 1]
then FOUND <- true
SAVE + J
If FOUND
then Repeat for J = SAVE, SAVE + 1, ..., I
Repeat for M = F{J], F[J] + 1, ..., R[J]
Q[M - 1] = QiM]
R[J] — Ri] - 1
F{J] — F{J] -1
else (entire queue structure is full)
Write(‘STACK OVERFLOW’)
Return
~) [Increment rear pointer]
Ri — Ri] +1
[Insert element]
QIRIM]
—Y
[Check front pointer]
If F{l] = TRUNC(M/N) « (I- 1)
then F{I] — F[i] + 1
[Finished]
Return
3-46
s ; as ,
g,(- e MD SE SES Oe ae e he
y — : , : f ithe? a wees Phe
ol atue Pegs reg
co. ta rid ait é ‘roe FRY +
’ ee, ©
se
. pore
ee oi
iwyieiale
‘ ae ks
het
CHAPTER 4
1. [Initializations]
TEMP «+ FIRST
ca
2. [Scan through list]
Repeat while TEMP ee NULL
P~I+1
TEMP <— LINK(TEMP)
3. [Finished]
Return(I)
1. [Valid K?|
IfkK <0
then ~\Write('INVALID Kk’)
Return
2. [Scan through list]
TEMP + FIRST
Repeat while K 54 1 and TEMP 54 NULL
K+K-1
TEMP + LINK(TEMP)
3. [Change info field if Kth node exists]
If TEMP = NULL
then Write(‘K TOO LARGE’)
else INFO(TEMP) + Y
4. [Finished]
Return
4-3
If SAVE = NULL
then FIRST — NEXT
else LINK(SAVE) + NEXT
6. [Finished]
Return
{ This procedure deletes all nodes within the range such that kmin <= x
<= kmax. }
var next,save:pointer;
begin
{ check for empty list }
if first <> nil
then begin
{ find last node whose key value < kmin }
next := first;
save := nil;
while(nextf.link < >nil)and(nextt.key<kmin)do
begin
save := next;
next := nextf.link
end;
{ check if no node found }
if nextf.key >= kmin
then begin
{ find first node whose key value > kmax }
while (nextf.link <> nil) and (nextt.key <= kmax) do
next := nextf.link;
{ reset link fields }
if nextf.key < kmax
then next := nil;
if save = nil
then first := next
else savef.link := next
end
end
end;
4)
7) Algorithm COLLEGE_REPORT. This algorithm creates a linked list of
student records ordered by student number. The information fields in a
typical student record include STUDENT_NO, NAME, COL, SEX, YEAR.
The first node in the list is given by FIRST, and the link fields are referenced
as LINK. Within this linear list there is a smaller linked list for each college.
The college names are stored in the vector COLLEGE, and pointers to the
first node of each list are stored in the respective locations of the vector
COL_HEAD, and the link fields are referenced as COL_LINK. Each college
linked list is ordered alphabetically by student name. COL_CT hold the
number of colleges. Several subalgorithms are referenced: INSORD_BY_.NO
is used to maintain the linear list ordered by student number;
INSORD_BY_NAME is used to maintain the college lists; UPDATE_LIST is
responsible for reflecting the changes made in an update transaction and
OUTPUT_REPORT causes the display of all student records from a specified
college.
1. [Initializations]
FIRST — NULL
COL_CT + 0
2. [Create linked list in order]
Read(STUDENT#)
Repeat while STUDENT# 999999
NEW <— NODE
STUDENT_NO(NEW) + STUDENT#
Read(NAME(NEW),COL(NEW),SEX(NEW),
YEAR(NEW))
Call INSORD_BY_NO(NEW)
Call INSORD_BY_NAME(NEW)
Read(STUDENT#)
Read(DUMMY_NAME,DUMMY_COL,DUMMY_SEX,DUMMY_YR)
3. [Update linked list]
Read(STUDENT#)
Repeat while STUDENT# 999999
Read(NEW_COL,NEW_YR)
Call UPDATE_LIST(STUDENT#,NEW_COL,NEW_YR)
Read(STUDENT#)
Read(DUMMY_COL,DUMMY_YR)
4. [Output college reports]
Read(COL_NAME)
Repeat while not end of file
Call OUTPUT_REPORT(COL_NAME)
Read(COL_NAME)
5. [Finished]
Exit
4-5
Procedure INSORD_BY_NO(P). This procedure places the node given
by P in the appropriate location within the linked list ordered by student
number.
4-6
[Empty college?|
TEMP + COL_HEAD|]]
If TEMP = NULL
then COL_HEAD|I] ~— P
COL_LINK(P) — NULL
Return
[New node precedes first node?|
If NAME(TEMP) > NAME(P)
then COL_HEAD|I] — P
COL_LINK(P) + TEMP
Return
[Search for predecessor in list]
FOUND + false
Repeat while COL_LINK(TEMP) +4 NULL and ~FOUND
If NAME(COL_LINK(TEMP)) > NAME(P)
then FOUND + true
else TEMP «+ COL_LINK(TEMP)
[Reset link fields]
COL_LINK(P) — COL_LINK(TEMP)
COL_LINK(TEMP) — P
[Finished]
Return
Procedure UPDATE_LIST(STUDENT#,NEW_COL,NEW_YR).
Given the student number of a record to be updated, and the updated values
for the COL and YEAR fields, this procedure implements those changes in the
record and the linked lists of the colleges.
4-7
If COL(SAVE) = NEW_COL
then Return
[Find head of old college list].
Eat 4
Repeat while COLLEGE|I] 54 COL(SAVE)
Petia
[Remove from old college list]
If COL_HEAD|I] = SAVE
then COL_HEAD|I] — COL_LINK(SAVE)
else TEMP + COL_HEAD|I]
Repeat while COL_LINK(TEMP) oe SAVE
TEMP «+ COL_LINK(TEMP)
COL_LINK(TEMP) — COL_LINK(SAVE)
[Reset new college list links]
COL(SAVE) — COL_NAME
Call INSORD_BY_NAME(SAVE)
[Finished]
Return
1. [Initializations]
COLLEGE|COL_CT+1] — COL_NAME
I— 1
[Find head of college list]
Repeat while COLLEGE|I] 4 COL_NAME
I+I+1
[College not found?|
If l-= COL_CT + 1
then Write('0 STUDENTS IN COLLEGE/BAD COLLEGE NAME’)
Return
[Output title and students in college}
Write(COL_NAME)
SAVE + COL_HEAD|I]
Repeat while SAVE NULL
Write(NAME(SAVE),STUDENT_NO(SAVE),SEX(SAVE),
YEAR(SAVE))
SAVE + COL_LINK(SAVE)
[Finished]
Return
4-8
Procedure INSERT_LINES(BLINE). Given BLINE, the line number of
the line preceding the point of insertion, this procedure processes text
insertions into the array FREE_TEXT. LINENUM holds BLINE’s line
number; SAVE holds the following line’s number; INDEX holds the index of
BLINE in the array, and LINK holds the link of BLINE. Three functions are
invoked: CONVERTCHAR returns the character equivalent of a given integer;
CONVERTNUM returns the integer equivalent of a given character;
FINDINDEX returns the array index of the line with the given line number.
LASTLINE is a global variable which holds the index of the last line in the
array. MAXLINE is the largest index possible.
1. [Initializations|
LINENUM «+ CONVERTNUM(BLINE)
INDEX + FINDINDEX(BLINE)}
2. [Appending to end of text?|
LINK « SUB(FREE_TEXT|INDEX],6,5)
If LINK = '00000!
then SAVE + 0
else SAVE + CONVERTNUM(LINK)
SUB(FREE_TEXT|INDEX],6,5) CONVERTCHAR(LASTLINE + 1)
3. [Move inserted text into free text]
Repeat for I = 1, 2,..., 9 while there remains insertion text
LASTLINE + LASTLINE pit
SUB(FREE_TEXT|LASTLINE],1,5) —
CONVERTCHAR(10*INDEX + I)
SUB(FREE_TEXT|LASTLINE],6,5) —
CONVERTCHAR(LASTLINE + 1)
SUB(FREE_TEXT[LASTLINE],11,80) + next line of inserted text
4. [Set link field of last inserted line]
SUB(FREE_TEXT[LASTLINE],6,5) ~ CONVERTCHAR(SAVE)
5. [Check for incomplete insertion]
If not end of insertion text
then Write(/NO ROOM FOR FURTHER INSERTION’)
6. [Call proc to renumber text file]
Call RENUMBER
7. [Finished]
Return
1. [Empty list?]
If LINK(FIRST) = NULL
then Return(NULL)
2. [Only one element?]
If LINK(FIRST) = NULL
then Return(FIRST)
3. [Reverse list]
PRED «+ NULL
Repeat while FIRST 54 NULL
TEMP + LINK(FIRST)
LINK(FIRST) — PRED
PRED + FIRST
FIRST «+ TEMP
4. [Return pointer to new list]
Return(PRED)
1. [Empty list?]
If START = NULL
then Return(false)
2. [Is X the first element?|
If KEY(START) = X
then DATA + INFO(START)
Return(true)
3. [Search for desired key]
TEMP + LINK(START)
PRED «+ START
FOUND + false
Repeat while TEMP 34 NULL and ~FOUND
If KEY(TEMP) = X
then FOUND < true
else PRED + TEMP
TEMP + LINK(TEMP)
4. [Was element found?|
If ~FOUND
then Return(false)
5. [Move element to front of list]
LINK(PRED) « LINK(TEMP)
LINK(TEMP) + START
START «+ TEMP
6. [Return desired information|
DATA + INFO(START)
Return(true)
13) Algorithm CUSTOMERS. This algorithm handles the processing of a
company’s list of customers with outstanding bills. The data structure used
requires two types of nodes: CUST.NODE has fields NAME, ADDR, TOTAL,
LINK, FIRST, and LAST; ITEM has fields COMMOD, OWING, and NEXT.
The entire structure is pointed at by CUSTOMER. Construction of the
structure is handled by procedure PURCHASE as new customers are added to
the list. Since searching is required by procedures PURCHASE, PAYMENT,
and BILL, it is implemented in a separate procedure, which is also capable of
inserting new elements depending on value of a flag parameter.
1. [Empty Structure?]
If CUSTOMER = NULL
then If FLAG
then P <= CUST_NODE
CUSTOMER+ P
LINK(P) + NULL
NAME(P) + CUST_NAME
ADDR(P) + ADDRESS
FIRST(P) + LAST(P) «— NULL
4-12
TOTAL(P) + 0
Return(P)
else Return(NULL)
2. [Insert at top of list?]
If CUST_NAME < NAME(CUSTOMER)
then If FLAG
then P <= CUST_NODE
LINK(P) — CUSTOMER
CUSTOMER+ P
NAME(P) + CUST_NAME
ADDR(P) + ADDRESS
FIRST(P) + LAST(P) + NULL
TOTAL(P) + 0
Return(P)
else Return(NULL)
3. [Check rest of list]
FOUND + false
SAVE + CUSTOMER
PRED «+ NULL
Repeat while SAVE 54 NULL and =FOUND
If NAME(SAVE) > CUST_NAME
then FOUND + TRUE
else PRED «+ SAVE
SAVE + LINK(SAVE)
4. [Insertion in list?]
If “FOUND
then If FLAG
then P <= CUST_NODE
LINK(P) + LINK(PRED)
LINK(PRED) «— P
NAME(P) «+ CUST_NAME
ADDR(P) + ADDRESS
FIRST(P) + LAST(P) — NULL
TOTAL(P) + 0
Return(P)
else Return(NULL)
5. [Return location of node already in list]
Return(SAVE)
4-13
[Input customer’s name, address, and number of purchases}
Read(CUST_NAME,ADDRESS OM)
[Find customer node]
C_NODE + SRCH _INS(CUST_ NAME,ADDRESS ame)
[Add an item node for each CES
Repeat thru step 5 for I = 1, 2, .... NUM
[Create and add node]
If FIRST(C_NODE) = NULL (no items in list)
then NEW <—ITEM
FIRST(C_NODE) + LAST(C_NODE) + NEW
NEXT(NEW) «— NULL
else NEW <—ITEM
SAVE «+ LAST(C_NODE) (mark current last node)
NEXT(SAVE) + LAST(C_NODE) + NEW (place at end of list)
NEXT(NEW) «— NULL
[Initialize ITEM fields and update total debt]
Read(COMMOD(NEW),OWING(NEW))
TOTAL(C_NODE) + TOTAL(C_NODE) + OWING(NEW)
[Finished]
Return
h-14
[Was commodity found?|
If -FOUND
then Write(/COMMODITY NOT FOUND IN LIST’)
Return
[Delete commodity from list]
If SAVE = FIRST(C_NODE) (is commodity first in list?)
then FIRST(C_NODE) — NEXT(SAVE)
else NEXT(PRED) ~ NEXT(SAVE)
[Was commodity last in list?]
If NEXT(PRED) = NULL
then LAST(C_NODE) — PRED
[No items left in list?]
If FIRST(C_NODE) = NULL
then If CLNODE = CUSTOMER (first node in list?)
then CUSTOMER + LINK(C_NODE)
else LINK(PRED) — LINK(C_NODE)
Return
9. [Update total debt]
TOTAL(C_NODE) «+ TOTAL(C_NODE) - OWING(SAVE)
10. [Finished]
Return
1. [Empty structure?]
If CUSTOMER = NULL
then Write('NO CUSTOMERS IN LIST’)
Return
[Print heading]
Write(‘'CUSTOMERS WITH OUTSTANDING DEBTS:')
[Traverse list]
SAVE + CUSTOMER
Repeat while SAVE oe NULL
Write(NAME(SAVE), TOTAL{SAVE))
SAVE + LINK(SAVE)
[Finished]
Return
4-17
LINK(NEW) + SPLIT
SPLIT + NEW
LINK(TEMP) + SPLIT.
Return
1. [Surround alink]
TEMP «— LINK(HEAD)
2. [Join circular list to availability list]
LINK(HEAD) + AVAIL
3. [Reset head of availability list]
AVAIL «+ TEMP
Return
1. [Valid K?|
IK <0
then Write(/INVALID K VALUE ',K)
Return
2. [Initializations]
P1 + LINK(S1PTR)
I+ 1
3. [Isolate SUB(S1,1,K)]
Repeat while P1 4 SIPTR and I < K
I+eI+1
P1 — LINK(P1)
MARK + LINK(P1)
OLD + Pl
4. [Link S2]
P2 — LINK(S2PTR)
Repeat while P2 - S22 TR
P < NODE
LINK(OLD) + P
INFO(P) + INFO(P2)
P2 + LINK(P2)
OLD «+ P
5. [Link last element of S2]
P <= NODE
LINK(OLD) + P
INFO(P) — INFO(P2)
6. [Link SUB(S1,K+1)
LINK(P — MARK
7. [Was SUB(S1,K+1) empty?|
If MARK = LINK(S1PTR)
then SIPTR+P
8. [Finished]
Return
EXERCISES SECTION 4-2.3 PAGE 291
4-21
RPTR(PRED) — NEW
LPTR(NEW) + PRE
PRED «+ NEW ‘
TEMP + LINK(TEMP)
4. [Complete links]
LPTR(HEAD) — PRED
RPTR(PRED) + HEAD
5. [Finished]
Return(HEAD)
4-23
LPTR(NEXT) «+ COMPANY
RPTR(COMPANY) «+ NEXT
Return ‘
3. [Move company node left if necessary]
NEXT + LPTR(COMPANY)
FOUND + false
Repeat while NEXT 54 NULL and — FOUND
If STOCK(NEXT) < QUOTE
then FOUND + true
else NEXT + LPTR(NEXT)
If NEXT = LPTR(COMPANY)
then RPTR(LPTR(COMPANY)) + RPTR(COMPANY)
LPTR(RPTR(COMPANY)) — LPTR(COMPANY)
LPTR(RPTR(NEXT)) + COMPANY
RPTR(COMPANY) + RPTR(NEXT)
RPTR(NEXT) + COMPANY
LPTR(COMPANY) + NEXT
Return
4. [No changes necessary]
Return
1. [Initializations]
TEMP + P
RESULT <— 0
2. [Evaluate each node and keep running total]
Repeat while TEMP +4 NULL
RESULT «+ RESULT + COEFF(TEMP) * XTPOWER_X(TEMP)
* Y{POWER_Y(TEMP)*Z{POWER_Z(TEMP)
3. [Finished]
Return(RESULT)
4-24
Function POLY_SUB(P,Q). Given two polyncmials whose first terms are
referenced by pointer variables P and Q respectively, this function subtracts
the second from the first and stores the difference in a third polynomial, the
head of which is returned by the function. In practice one wou!d combine
algorithms POLY_ADD and POLY_SUB into a more general algorithm. The
small difference in processing could be controlled by a single boolean variable.
LAST is a global variable.
1. [Initializations]
R «— NULL
PSAVE + P
QSAVE + Q
[End of any polynomial?|
Repeat thru step 4 while P ee NULL and Q x NULL
[Get values for each term]
Al — POWER_X(P)
A2 — POWER_X(Q)
C2 + POWER_Z
D1 — COEFF(P)
D2 + -COEFF(Q)
[Compare terms]
If (Al = A2) and (B1 = B2) and (C1 = C2)
then If D1+D2 0
then R + POLYLAST(A1,B1,C1,D1+D2,R)
P + LINK(P)
Q + LINK(Q)
else If(A1>A2) or ((Al=A2) and (B1>B2)) or ((A1=A2) and
(B1=B2) and (C1>C2))
then R + POLYLAST(A1,B1,C1,D1R)
P + LINK(P)
else R + POLYLAST(A2,B2,C2,D2,R)
Q + LINK(Q)
[Not at end of one of polynomials?|
IfP = NULL
then LINK(LAST) + COPY(P)
else Repeat while Q ee NULL
R + POLYLAST(POWER_X(Q),POWER-Y(Q),
POWER_Z(Q),-COEFF(Q),R)
Q + LINK(Q)
[Restore initial pointer values for P and Q]
P -— PSAVE
Q + QSAVE
4-25
i [Return pointer of difference polynomial]
Return{R)
4-27
5 ) Function POLY_MUL(A,B). Given two polynomials whose first terms are
referenced by pointer variables A and B, respectively, and Function
POLY_ORDER of Exercise 3, in this section, this function multiplies these
two polynomials together, and returns a pointer to the resultant polynomial.
The original polynomials are to remain unchanged. FRONT, SAVEA,
SAVEB, and NEW are temporary pointer variables.
4-29
~J Function POLY_INT(P,VAR). Given a polynomial whose first term is
referenced by the pointer variable P, and a character string variable VAR
which takes on the value of one of 'X', 'Y', or 'Z’, this function integrate? the
polynomial with respect to the variable VAR and returns a pointer to the first
term of the integral. The original polynomial remains unchanged. NEW,
SAVE, and SAVEP are temporary pointer variables.
4-30
8) Function POLY_DIF(P,VAR). Given a polynomial whose first term is
referenced by the pointer variable P, and a character string variable VAR,
which takes on the value of one of /X’, 'Y', or ‘Z’, this function differentiates
the polynomial with respect to the variable VAR and returns a pointer to the.
derivative polynomial. The original polynomial remains unchanged. NEW,
SAVE, and SAVEP are temporary pointer variables.
4-31
9) Procedure POLY_PRINT(P). Given a polynomial whose first term is
referenced by the pointer variable P, this procedure prints the polynomial.
The format of the output will be as follows:
1) program midsq(input,output);
var varname:string;
result:real;
n:integer;
GARB EEEEE ORO OBEER EEO EESBS OBE ABE EEE AA TEE IA AAI ATE IE}
#include ‘getline.’ ;
#include 'length.i’;
[ABBE EE EEE EEO SEES EES ABE BEBE EEE EE SAAB ACRE EIT AEE +}
4-32
procedure precond(varname:string;var i:real);
var j:integer;
begin
1:= 1;
{ pass through each letter of varname }
for j := 1 to length(varname) do
i := i * ord(varname({j])/5
end;
EE ISS EBSD SEAT IAI IITA EIA
EEO RBBB EEE HEBER S
GABE E
function modr(a,b:real):real;
begin
modr := ((a/b) — trunc(a/b)) * b
end;
GABE BEER EEE E EERE D EOE EEEIEEE EEA AA AAT SATE aaa Aa
function power(a,b:real):real;
begin
power := exp(b#ln(a))
end;
[EHH E REHAB SESS S OEE AIEEE OBE EEE AEE ABER AAI Ee}
function size(number:real):integer;
var temp:real;
count:integer;
begin
{ count number of digits in number }
4-33
temp := number;
count := 0;
while (temp > 1.0) do
begin
temp := (temp / 10);
count := count + 1
end;
size := count
end;
FABER SRE ESSE SE EEO AAAS ESAS SOSA ACEO IEE EEE EERE te #4}
function hash(key:real;n:integer):real;
var square:real;
s:integer;
begin
{ apply hashing procedure }
square := power(key,2.0);
8 := size(square);
ifs <=n
then hash := square
else begin
square := square / power(10,round((s-n)/2.0));
hash:= modr(square,power(10,n));
end
end;
begin
read|n(n);
while not eof do
begin
getline(varname);
precond(varname, result):
writeln(’VARIABLE = ’:12,varname:length(varname),’ PRECOND = ’:12 J
4-34
VARIABLE = __ temp PRECOND = 228846.28 HASHED TO 6
VARIABLE = num PRECOND = 11222.64 HASHED TO 94
VARIABLE = sum PRECOND = 11732.76 HASHED TO _ 65
VARIABLE = location PRECOND = 43828497296.38 HASHED TO 25
VARIABLE = address PRECOND = 1890617222.40 HASHED TO 81
VARIABLE = name PRECOND = 187945.65 HASHED TO 35
VARIABLE = phone PRECOND = 4596617.63 HASHED TO 93
VARIABLE =_ grade PRECOND = 3681163.97 HASHED TO_ 68
VARIABLE = link PRECOND = 213554.88 HASHED TO 56
VARIABLE = info PRECOND = 209230.56 HASHED TO 74
VARIABLE = data PRECOND = 174631.04 HASHED TO 60
2)
“ program fold(input,output);
function size(number:integer):integer;
var temp,count:integer;
begin
{ count number of digits in number }
temp := number;
COUnU >——10;
while (temp <> 0) do
begin
temp := temp div 10;
count := count + 1
end;
size := count
end;
[ABB CR
BEER E EEE EERE E BEES EEE EECAO EEE ECHO CDE E oiereaiii)
function power(a,b:integer):integer;
var result,i:integer;
fae
begin
result := 1;
for i:=1tobdo
result := result * a;
power := result
end;
var sum,rest,s:integer;
begin
{ engage loop to handle each digit }
rest := key;
s := size(key);
while (s > n) do
begin
- sum := sum + (rest div (power(10,s—n)));
rest := (rest) mod (power(10,s—n));
Si=s-n
end;
hash := (sum + rest) mod (power(10,n))
end;
EB EEE EERE ESE EEE EOS ISSO EEEE E AEE EEE IAA IE EAI ES }
begin
{engage loop to process all data }
readIn(n);
while not eof do
begin
readIn(key);
writeln’INTEGER GENERATED FROM ‘key, ’ = ’,hash(key,n))
end
end.
h-36
INTEGER GENERATED FROM 15926487 = _—510
INTEGER GENERATED FROM 48159263 = —-186
INTEGER GENERATED FROM 78451236 = = 332
INTEGER GENERATED FROM 98776532 = 784
INTEGER GENERATED FROM 55332246 = 921
INTEGER GENERATED FROM 52884759 == —_ 434
INTEGER GENERATED FROM 99999999 = 97
INTEGER GENERATED FROM 55465787 = =. 298
INTEGER GENERATED FROM 23212141 = 394
INTEGER GENERATED FROM 87898999 = 966
INTEGER GENERATED FROM 65485278 = —584
The method which distributes the keys most evenly over the range depends
upon the domain, i.e. the particular set of keys. For example, when a set of
similar eight-digit keys was used, the order of the best performing methods
was midsquare, division, and folding. When a set of random, one to eight-
digit keys were used, there was no observable difference in distribution
(partially due to the small set of test keys and the original randomness in the
set of test keys). In essence, the distribution method should be chosen
according to the set of keys used if any information is available about them.
If the set of keys is fixed and well known, then a ‘‘custom”’ hashing function
can be created to best distribute the particular set. Such a function is known
as a distribution-dependent hashing function. The methods discussed up until
this point have all been distribution independent.
P 62 75 | 4 4 |4
Sri Fuiiy 3 165|]
91120
66 ——> 91 ——>120
NULL
8
36 ——> 8
61—>36 ——>8
HH
NLT
OHONAAAnNInrB 8 —»> -36 —> -61
1. [Trivial Case]
If P = NULL or Q = NULL
then Return(NULL)
2. [Initializations]
SAVEM — NULL
SAVEP < P
SAVEQ + Q
3. [Allocated head node for place holding list]
HEAD «+ PLACE_HOLDER + INSERT(0,NULL)
4. [Chain down list P]
Repeat thru step 7 while P 6 NULL
5. [Chain down list Q
If COEF(P) 2 0
then Q + SAVEQ
PART + NULL
C+-0
Repeat while Q +4 NULL
(Calculate value for and insert next node)
4-38
PRODCF + COEF(P)
* COEF(Q) + C
PART «+ INSERT(PRODCF mod MAX, PART)
C + CHOP(PRODCR/MAX)
(Next node from list Q)
Q + LINK(Q)
(Final carry?)
C0
then PART « INSERT( C mod MAX, PART)
(Reverse the resulting list)
PART «+ REVERSE(PART false)
(Incorporate the place holding list)
LINK(PLACE_HOLDER) + PART
(Add partial products)
Tl + SAVEM
T2 — LINK(HEAD)
SAVEM + ADDITION(SAVEM,T2)
6. [Enlarge the place holding list]
HEAD + INSERT(0,HEAD)
7. [Next node from list P]
P + LINK(P)
8. [Restore initial values of pointer variables P and Q]
P — SAVEP
Q + SAVEQ
Return(SAVEM)
a
Case ‘DELETE’:
Call DELETION(STUDENT_NAME)
Case ‘UPDATE’:
Call UPDATE(STUDENT_NAME)
Case 'OUTPUT!:
Call OUTPUT(STUDENT_NAME)
Default:
Write(‘INVALID COMMAND’)
2. [Finished]
Exit
1. [Delete record]
LINK(pred of record STUDENT <STUDENT_NAME>) —
LINK(record STUDENT <STUDENT_NAME>)
2. [Free record]
DISPOSE(record STUDENT <STUDENT_NAME>)
3. [Finished]
Return
4-0
2. {Record information]
MARK[ASSIGN#| of STUDENT <STUDENT_NAME> + NEWMARK
GRADE of STUDENT<STUDENT_NAME> +
GRADE of STUDENT <STUDENT_NAME> + NEWMARK
3. [Finished]
Return
4-41
var studentname,command:string;
save, i:integer;
loc:pointer; A
table:array[0..9] of pointer;
(GABBBE BEEBE ESR ABO EOEDEBE EOS EES EE HEB Ean bobbin s44}
#include 'length.i!;
[EBB B
BSH HE ECE E
ESSE BE HOUSES OSHS EEE FEED Ha olor ints }
{ This procedure reads data from the current input line until a blank or and
end of line is detected. }
var i,j:integer;
ch:char;
begin
{ read data }
ices]:
ch :== ’?’:
while (i < 80) and (ch <> ’’) and (not eoln) do
begin
read(ch);
word|i] := ch;
i:=i+1
end;
{ adjust to accommodate for blank }
if not eoln
then i:=1-1;
{ set string delimiter }
word|i] := ’|’;
{ pad with blanks }
for }:=1+ 1to 80 do
word|j] :=
end;
procedure insertion(loc:pointer;studentname:string;save:integer);
{ This procedure inserts a new record associated with studentname into the
equivalence class indexed by save if the insertion is unique. }
4-h2
var p:pointer;
isinteger;
begin
{ check for multiple insertions}
if loc <> nil
then begin
{ output error message }
writeln;
write(’**#ERROR#*** ATTEMPTED INSERTION OF RECORD ’);
writen’ ASSOCIATED WITH ’ studentname:length(studentname));
writeln(’DISALLOWED BECAUSE OF MULTIPLE INSERTION’) I
readIn;
end
else begin
{ allocate new node and insert into equivalence class }
new(p);
pf-link := table[save];
table[save] := p;
pf.contents.name := studentname;
get(pf.contents.college);
readIn(pt.contents.id);
for i := 1 to 10 do
pt.contents.mark[i] := 0;
pt.contents.grade := 0;
end
end;
(SOR RE RE IE EEE REESE EE EEE EE EEE EEE EEE EEE EEE EEE EE)
procedure deletion(loc:pointer;studentname:string;save:integer);
{ This procedure deletes the student record associated with studentname from
the equivalence class indexed by save, provided the record exists. }
var temp:pointer;
begin
{ Check if record exists }
if loc = nil
then begin
{ output error message }
writeln;
write(’**#ERROR*** ATTEMPTED DELETION OF RECORD ’);
writeln(’ ASSOCIATED WITH ’studentname:length(studentname));
4-43
writeln(’DISALLOWED BECAUSE OF MISSING INSERTION’);
readIn
end
else begin
readln;
{ delete record }
if table[save] = loc
then table[save] :== loct.link
else begin
temp := table[save];
while tempf.link <> loc do
temp := tempf.link;
tempf.link := locf.link
end;
cdispose(loc)
end
end;
(SS ER EE EE EE EE IE EE EE EE EE)
procedure update(loc:pointer;studentname:string);
begin
{ Check for valid student name }
if loc = nil
then begin
writeln;
write(’***ERROR##* ATTEMPTED UPDATE OF RECORD ’);
writeln(’ASSOCIATED WITH ’ studentname:length(studentname));
writeln(’DISALLOWED BECAUSE OF MISSING INSERTION. ’);
readin
end
else begin
readIn(assign,newmark);
loct.contents.mark{assiga] = newmark;
locf.contents.grade := locft.contents.grade + newmark
end
eud;
[BREESE EE EEE EERIE EEA IEEE EA EATS IEEE EES IEEE EAST AE ATTA ESSE AAAS
h-hh
procedure out(loc:pointer;studentname:string);
var i,j:integer;
begin
{ Check for all students }
if studentname = ’alll’
then for i := 0 to 9do
begin
loc :== table[il;
while loc <> nil do
begin
writeln;
writeln(’“NAME: ’:9,locf.contents.name:length
(lect .contents.name));
writeln(’;COLLEGE: ’:9 loct.contents.college:length
(loc f .contents.college));
writeln(’ID: ’:9,locf.contents.id:6);
write("MARKS: °:9);
for} := 1to10do
write(loct.contents.mark|j]:6);
writeln;
writeln(’(GRADE: ’:9,locf.contents.grade:6);
loc := loct.link
end
end
else if loc = nil
then begin
writeln;
write(’**##*ERROR*** OUTPUT OF RECORD ’);
writeln(/ASSOCIATED WITH ’ studentname:length
(studentname));
writeln(’DISALLOWED DUE TO MISSING INSERTION’); ’
end
else begin
writeln;
writeln(’NAME: ’:9,locf.contents.name:length
(loc }.contents.name));
writeln(’COLLEGE: ’:9,loct.contents.college:length
{loct .contents.college});
writeln(’ID: ’:9,locf .contents.id:6);
writeln(’GRADE: ’:9,locf .contents.grade:6)
end;
b-4s
readln
end;
function hash(symbol:string):integer;
var tl1,t2:integer;
begin
t1 := ord(symbol|1]);
t2 := ord(symbol|3});
hash := tl + t2
end;
var temp:pointer;
found:boolean;
begin
{ determine index into table }
save :== hash(studentname) mod 10;
temp := table[savel;
found := false;
while (temp <> nil) and (not found) do
begin
if tempt.contents.name = studentname
then found := true
else temp := tempf.link
end;
student :== temp
end;
h-h6
EBA E EEA IGE
ES E AI ATA TIAA }
LEB O RECESS DEBE
begin
{ initializations }
for i:= 0 to9do
table[i] := nil;
{ engage loop to process all data }
while nct eof do
begin
{ read command and student name }
get(command);
get(studentname);
{ determine location of record }
loc :== student(studentname,save);
get(command);
get(studentname);
{ determine location of record }
loc := student(studentname,save);
{ call appropriate procedure to process command }
if command = ’insertion|’
then insertion(loc,studentname,save)
else if command = ’deletion|’
then deletion(loc,studentname,save)
else if command =.’update|’
then update(loc,studentname)
else if command = ’output]’
then out(loc,studentname)
else begin
writeln;
writeln(’***ERROR*** INVALID COMMAND ’
command:length(command));
writeln(’/ENTRY IGNORED’);
readin
end
end
end.
4-47
update l.witkowicz 1 85
update k.manson 1 80
update s.mcdonald 1 49
update d.manegre 1 99
update c.letilley 1 85
_ update l.witkowicz 2 88
update k.manson 2 75
update c.letilley 2 89
update d.manegre 2 98
update s.mcdonald2 25
output s.mcdonald
deletion s.mcdonald
insertion k.manson commerce 813695
deletion f.flintstone
update b.rubble 1 65
output m.mouse
delete d.duck
output all
RESULTS:
NAME: s.mcdonald
COLLEGE: arts
ID: 802000
MARKS: 49 25 0 0 0 0 0 0 0 0
GRADE: 104
NAME: k.manson
COLLEGE: arts
ID: © 802572
MARKS: 80 75 0 0 0 0 0 0 0 0
GRADE: 155
NAME: c.letilley
COLLEGE: commerce
ID: 801427
MARKS: 85 89 0 0 0 0 0 0 0 0
GRADE: 174
NAME: l.witkowicz
COLLEGE: arts
ID: 812156
MARKS: 85
GRADE: 173
NAME: d.manegre
COLLEGE: commerce
ID: 813827
MARKS: 99 98
GRADE: 197
4-49
CHAPTER 5
Proof by induction: If we know the rule holds for a digraph of n nodes, and
we can show that it also holds for » + 1 nodes, then we have proved the rule
holds for a digraph with n or n + 1, or n + 2 or... nodes. If the number of
nodes n == 1, the rule holds because the indegree = 0, the outdegree = 0, and
the number of edges = 0. Now assume that for a graph of n nodes the sum of
indegrees of all the nodes equals the sum of outdegrees of all the nodes and
the number of edges of the graph.
0: ©) 1:
O ©
I>
Pe
> > oS
pole. ag
Vi, V4, V3
Vis V2 3
Wap 27 Mavs
INDEGREE | OUTDEGREE
acyclic digraph:
B=2
5)
O
6) With 3 nodes, you can have two directed trees or three ordered trees.
8) Proof by Induction: If we know that the rule holds for a tree with n, terminal
nodes and we can show that it also holds for n, + 1 terminal nodes, then we
have proved the rule holds for a tree with ny or ny + 1 or ny + 2 or ... nodes.
For ny = 1 (ie. a single node in the tree) then 2(n,- 1) = 0 equals the
number of edges as expected. Now assume that for some nm, we have the
number of edges equal to 2(i¢ — 1).
oon
we added two new terminal nodes and removed X as a terminal node. If
before we had for nz terminal nodes, 2(n, — 1) edges, we now have for ny + 1
terminal nodes, 2(n, — 1) + 2 = 2((m_ + 1) — 1) edges.
5-4
corresponds to Figure 6-1.16
Proof by induction: If we can show that for some number of nodes n that
there are n + 1 null links, and from this show that for n + 1 nodes there are
(n + 1) + 1 =n + 2 null links, this then proves that the rule holds for n or n
+ lorn+2or... nodes. For n = 1, this is clear since a tree of one node has
n + 1 = 2 null links. Now assume for some tree consisting of n nodes that
there are n + I null links.
pep
CASE 2: Inserting node P between nodes X and Y.
The insertion of node P increases the number of nodes by 1 to n + 1. The
pointer from X to Y is changed to a poiater from X to P, and a pointer from
P to Y is created. This means that the number of null links of X and Y
remains the same, bat one null link is added to the tree from node P,
increasing the number of null links from n + 1 to (n + 1) + 1. Thus for a
tree of n + i nodes, there are (n + 1) + 1 =n + 2 nuli links.
1. [Initializations]
P— T
TOP + 0
to [Engage loop to traverse tree]
Repeat thru step 4 while -EMPTY(S) or P 4 NULL
3. [Stack nodes of !eft chain]
Repeat while P 54 NULL
PUSH(S,P,TOP)
P + LPTR(P)
4. [Process node]
P + POP(S,TOP)
Write(INFO(P))
P + RPTR(P)
5. [Finished]
Return
b=6
—-NA ND -NE NF
—-NA ND -NE -NF NULL
-NA ND -NE -NF
—-NA ND -NE NF F CBF
-NA ND -NE
-~NA ND NE E CBFE
—-NA ND
—~NA -ND NG NULL
-NA —-ND NG
-NA -ND -NG NULL
~NA -ND -NG
—-NA -ND NG G CBFEG
-NA -ND
—-NA ND D CBFEGD
-NA
NA A CBFEGDA
INORDER 125 240 244 246 467 517 725 790 800 822 837 848 885 991
POSTORDER = 240 125 244 467 246 517 822 848 837 855 800 790 991 725
PREORDER 725 517 246 244 125 240 467 991 790 800 855 837 822 848
CONVERSE 991 855 848 837 822 800 790 725 517 467 246 244 240 125
INORDER
CONVERSE 848 822 837 855 800 790 991 467 240 125 244 246 517 725
POSTORDER
CONVERSE 725 991 790 800 855 837 848 822 517 246 467 244 125 240
PREORDER
5=8
8) Function POSP(X). Given
threaded for postorder traversal,
X, the address of a node in a binary tree
this function returns the address of the
postorder predecessor of X.
Function COPY(T). Given a tree with head node T, this function creates
an equivalent tree, and returns a pointer to its head node. Stack S is used to
stack right branches of the original tree; stack COPYS is used to stack right
branches in the new tree. TOP is an index to S$; COPYTOP is an index to
COPYS. X, P, and Q are temporary pointer variables. The function EMPTY
returns true if the given stack is empty; false otherwise.
eo
else Q <= NODE
LPTR(X) — Q
P + LPTR(T)
3. [Engage loop to traverse tree}
Repeat thru step 5 while P 54 NULL or -EMPTY(S)
4. [Descend left chain]
Repeat while P 54 NULL
INFO(Q) — INFO(P)
If LPTR(P) 4 NULL
then Y <= NODE
LPTR(Q) + Y
else LPTR(Q) — NULL
If RPTR(P) 4 NULL
then Y <= NODE
RPTR(Q) + Y
PUSH(S,RPTR(P),
TOP)
PUSH(COPYS,RPTR(Q), COPYTOP)
else RPTR(Q) — NULL
If -EMPTY(S)
then P + LPTR(P)
Q + LPTR(Q)
5. [Get right branch]
P + POP(S,TOP)
Q « POP(COPYS,TOP)
6. [Finished]
Return(X)
5-10
Function IPREP(X). This function returns the preorder predecessor of a
given node, X, in a binary tree threaded for inorder traversal.
a7 hs
then Return{K)
2. [Follow right chain until thread found]
Ko X
Repeat while kK > 0
K ~ RPTR(K)
K + |K|
If RPTR(K) < 0
then Return(K)
else K — RPTR(K)
Repeat while (LPTR(K) > 0) or (RPTR(K) > 0)
If LPTR(K) > 0
then K ~— LPTR(K)
‘else K + RPTR(K)
Return(K)
12) Function SIMILAR(P,Q). Given two binary trees, whose roct nodes are
reference by P and Q, this function returns true if it finds the trees to be
similar; false otherwise.
The next root indicated by the preorder list is B, and according to the inorder
list, C is its left subtree and Dis its right. We now have:
S212
This can be continued until we have:
SS ee
More formally, we can give a inductive proof. First note that a tree of 0 or 1
nodes is clearly defined by its preorder and inorder traversals. Now we can
hypothesize that if, for a given binary tree, the preorder and inorder traversals
uniquely define the root node and the nodes in the left and right subtrees of
the root, then the preorder and inorder traversals uniquely define any binary
tree. Finally we want to show that the traversals define the root node, and
the traversals indicate which nodes are in each of the left and right subtrees.
To show that the traversals define the root node, we note that according
to the definition of a preorder traversal, the first node in the preorder list
must be the root of the tree.
To show that the traversals indicate which nodes are in each of the left
and right subtrees, note that the definition of inorder traversal indicates that
the nodes in the left subtree are listed to the left of the root node, and
similarly for the nodes in the right subtree.
Therefore, every binary tree is uniquely defined by its preorder and
inorder traversals.
It can be shown in a similar manner that every binary tree is uniquely
defined by its postorder and inorder traversals, the only difference being that
SNS
the root node of the tree will be given by the last node in the postorder
traversal.
On the other hand, preorder and postorder traversal orders do not
uniquely define a binary tree. Consider the preorder traversal ABC and
7
postorder traversal CBA. The following trees all correspond to those orders:
5-14
14) Function COUNT(T). Given a pointer to the head node of a threaded
binary tree, T, this function counts the number of leaf nodes in that tree.
1, [Initializations]
HEAD <— NODE
LPTR(HEAD) — -HEAD
RPTR(HEAD) — HEAD
2. [Construct the tree]
Repeat while there remains input data
Read(NAME)
Call INSERT(HEAD,NAME)
3. [Traverse the tree]
P — LPTR(HEAD)
Repeat while P 4 HEAD
Write(INFO(P))
P — INSUCC(P)
4. [Finished]
Exit
Bale
INFO(NEW) — DATA
LPTR(NEW) — LPTR(HEAD)
RPTR(NEW) — -HEAD
LPTR(HEAD) + NEW
else Call INSERT(LPTR(HEAD),DATA)
Return
[Check right subtree]
If DATA > INFO(HEAD)
then (attempt insertion)
If RPTR(HEAD) < 0
then NEW <= NODE
INFO(NEW) «— DATA
LPTR(NEW) + — HEAD
RPTR(NEW) — RPTR(HEAD)
RPTR(HEAD) — NEW
else Call INSERT(RPTR(HEAD),DATA)
Return
[Multiple insertion attempted]
Write(/INSERTION DISALLOWED: NODE ALREADY EXISTS’)
Return
i [Initializations]
PATH
2 [Call procedure to find longest path]
Call LONGST(ROOT,PATH)
[Output result]
Write(‘DIAMETER = ',LENGTH(PATH))
Write(/PATH OF THAT LENGTH: ',PATH)
[Finished]
Return
ze
ean|=
r
mS
5-16
Return(T)
2. [Has node been found]
If INFO(T) = DATA
then (empty left subtree?)
If LPTR(T) = NULL
then Return(RPTR(T))
else (empty right subtree?)
If RPTR(T) = NULL
then Return({LPTR(T))
else (both subtrees exist)
SUCC + RPTR(T)
PRED + T
(find inorder successor)
Repeat while LPTR(SUCC) +4 NULL
PRED «+ SUCC
SUCC + LPTR(SUCC)
(replace node with inorder successor)
If PRED = T
then RPTR(PRED) + RPTR(SUCC)
else LPTR(PRED) + RPTR(SUCC)
LPTR(SUCC) + LPTR(T)
RPTR(SUCC) + RPTR(T)
Return(SUCC)
3. [Branch right or left]
If DATA < INFO(T)
then LPTR(T) ~ RECDEL(LPTR(T),DATA)
else RPTR(T) — RECDEL(RPTR(T),DATA)
4, [Finished]
Return(T)
Bato
else PTR + RPTR(P)
Repeat while PTR 54 NULL
P+ PTR ’
If X < INFO(P)
then PTR + LPTR(P)
else If X > INFO(P)
then PTR + RPTR(P)
else Write(/DUPLICATE ENTRY’)
Return
3. [Insert node]
NEW <= NODE
INF O(NEW) + X
LPTR(NEW) + RPTR(NEW) + NULL
If X < INFO(P)
then LPTR(P) + NEW
else RPTR(P) — NEW
4. [Finished]
Return
5-20
2. [Process node}
Write(INFO(T))
3. [Traverse right subtree]
Call CONPRE(RPTR(T))
4, [Traverse left subtree]
Call CONPRE(LPTR(T))
5. [Finished]
Return
pre
EXERCISES SECTION 5-1.4 PAGE 366
1) CURRENT
INPUT STAR LEVEL
PRED LPTR
<X LEVEL LOC (PRED_LOC ) rep foe )
0 0 L
la, ONT 1Na 1 Na NT Nee NUE
2b ONT 1Na 2Nb 2 Nb 1 Na Nb NULL
3d ONT 1Na 2Nb 3Nd_ 3 Nd 2 Nb Nd ' NULL
2c 2 Ne 3 Nd
ONT 1Na 2Nb 2 Nb Ne
3e ONT 1Na2Nb 3Ne 3 Ne 2 Ne Ne NULL
3f ONT 1Na2Nb 3Nf 3 Nf 3 Ne NULL Nf
4 1 Ng 3 Nf
2 Nb
1 Na Ng
2h ONT 1Ng 2Nh 2 Nh 1 Ng Nh NULL
3j ONT 1Ng 2Nh 3Nj 3 INj eee: Nh Nj NULL
3k ONT 1Ng 2Nh 3Nk 3 Nk 3 Nj NULL Nk
2i 2 Ni 3 Nk
2 Nh Ni
31 ONT 1Ng 2Nh 3NI 3 Nit <2 Ni Nl NULL
Be a eee
1. [Initialize node]
P < NODE
INFO(P) — PRED_NAME
LPTR(P) — NULL
If PRED. NAME = '/HEAD‘
then RPTR(P) + P
else RPTR(P) — NULL
2. [Read data for next node]
Read(LEVEL,NAME)
If LEVEL = -1
then Return(P)
3. [Compare level]
If LEVEL > PRED_LEVEL
then LPTR(P) — RCONVERT(LEVEL,NAME)
else If LEVEL = PRED_LEVEL
then RPTR(P) ~ RCONVERT(LEVEL,NAME)
poe
If LEVEL > PRED_LEVEL
then Write(/ MIXED LEVEL NUMBERS’)
: Return(NULL)
else PRED_LEVEL «+ LEVEL
PRED_NAME «+ NAME
4, [Return pointer to tree]
Return(P)
oe3
[Delete first subtree?]
ifl=1
then If LPTR(N) 4 NULL
then LPTR(N) — RPTR(LPTR(N))
else Write(/ERROR: SUBTREE DOES NOT EXIST’)
Return
[Initialize with first subtree]
P — LPTR(N)
[Find (I — 1)st subtree]
Repeat for J = 2, 3, ..., 1- 1 while RPTR(P) 44 NULL
P + RPTR(P)
[Check if subtree exists]
If RPTR(P) = NULL
then Write(/ERROR: SUBTREE DOES NOT EXIST’)
Return
[Delete subtree]
RPTR(P) + RPTR(RPTR(P))
[Finished]
Return
5-24
EXERCISES SECTION 5-1.5 PAGE 371
2) Procedure SEQ _POST(POS). Given the vector position of the root node
of a preorder sequentially stored binary tree, this procedure traverses the tree
in postorder.
Dr 2D
[Check for valid nodes]
If (0 <X < Nand0 <Y <N)
then Write(/ILLEGAL NODE INDEX’)
Return
[Stack path from X to Y or HEAD]
TOPX + 1
SX[TOPX] — X
Repeat while SX[TOPX] 0 and SX[TOPX] 4 Y
TOPX + TOPX + 1
SX[TOPX] — FATHER|SX[TOPX -1]]
[If required, stack path from Y to X or HEAD]
TOPY = 1
SY[TOPY] + Y
Repeat while SY[TOPY] 0 and SY[TOPY] 4 X
TOPY — TOPY +1
SY[TOPY] — FATHER[SY[TOPY — 1]]
[Delete redundant paths]
If SY[TOPY] = X
then TOPX+1
else If TOPX ~ 1 and TOPY 41
then Repeat while SX[TOPX - 1] = SY[TOPY - 1]
TOPX
+ TOPX - 1
LORY = TOPY 1
[Print path from X to Y|
Repeat for l=) 2 a TOPK = 1
Write(SX{]])
Repeationl=—TOPY.tOPy 1.4
Write(SY[I])
o3 [Finished]
Return
Note that it is possible to use a single array and fill it from both directions
rather than using two arrays. This would lower memory requirements.
ALL OPERATIONS:
If both operands are constants, then a new constant node representing
the result of the constant expression should be created.
5=26
'_I- If the second operand is zero, then result is evaluated to yield the first
operand only. If the first operand is zero, then the result is evaluated to yield
the second operand, as a subtree of the unary minus.
‘/': Tf the first operand is zero, then the result is evaluated to a constant
node equal to zero. If the second operand is zero, then an error condition
should be raised. It the second operand is one, then result is evaluated as the
first operand only.
't'; If both operands are zero, then an error condition should be raised. If
the second operand is zero then the result is evaluated to a constant node
equal to one. If the second operand is one or the first operand is zero or one,
then the result is evaluated as the first operand only.
'g!: If the operand is a constant, then the negative of the constant should be
stored in the symbol table and the unary minus operator removed.
Case 7: (exponentiation) °
TEMP1 + CREATE2(MAKE_NODE('~'),RPTR(ROOT),
MAKE_NODE('1'))
TEMP2 + CREATE2(MAKE_NODE('{!),LPTR(ROOT), TEMP1)
TEMP3 — CREATE2(MAKE_NODE('*!), RPTR(ROOT), TEMP2)
TEMP4 «+ CREATE2(MAKE_NODE('*'),OPERAND1,TEMP3)
TEMP5 + CREATE1(MAKE_NODE('LN’),LPTR(ROOT))
TEMP6 + CREATE2(MAKE_NODE('*'), TEMP5,OPERAND2)
TEMP7 — CREATE2(MAKE_NODE('t!), LPTR(ROOT),
RPTR(ROOT))
TEMP8 «+ CREATE2(MAKE_NODE('*'), TEMP6,TEMP7)
Return(CREATE2(MAKE_NODE('+!),
TEMP4, TEMP8))
3) The following modifications are necessary to include the trigonometric
functions sin, cos and tan in function DIFFER: Add the following cases to
step 5 assuming the given symbol table:
TYPE MEANING
constant
variable
+ (addition)
— (subtraction)
* (multiplication)
/ (division)
t (exponentiation)
9 (unary minus)
LN (logarithm)
SIN
COS
AON TAN
OoPCMNABMA
Se
__ SIMPLIFICATIONS
O+x—-x x+0—-x
0-x— 6x x-O—-+x
0*x—0 x*0—-0
1*x—-x x*¥1—41
0/x-0 xf/1l—+x
xfo—-l 0Otjx—-0
xfl—-x lftx-1l
0x+ -x
5-28,
1. [Check for empty tree or leaf node]
If E = NULL
then Return
If TYPE(E) = 0
then Return
2. [Breakdown problem|
Call OPTIMIZE(LPTR(E))
Call OPTIMIZE(RPTR(E))
3. [Check for unary /binary operators]
If LPTR(E) 54 NULL and RPTR(E) 4 NULL
then (check for two constants)
If TYPE(LPTR(E)) = 0 and TYPE(RPTR(E)) = 0
then Select case (TYPE(E))
Case '+’:
RESULT — VALUE(RPTR(LPTR(E))) +
VALUE(RPTR(RPTR(E)))
Case !—!:
RESULT — VALUE(RPTR(LPTR(E))) -
VALUE(RPTR(RPTR(E)))
Case '*!:
RESULT — VALUE(RPTR(LPTR(E))) *
VALUE(RPTR(RPTR(E)))
Case !/':
RESULT + VALUE(RPTR(LPTR(E))) /
VALUE(RPTR(RPTR(E)))
Case? feo
RESULT — VALUE(RPTR(LPTR(E))) t
VALUE(RPTR(RPTR(E)))
TYPE(E) + 0
VALUE(RPTR(E)) + RESULT
else Select case (TYPE(E))
Case '+!:
If EVAL(LPTR(E)) = 0
then E+ RPTR(E)
else If EVAL(RPTR(E)) = 0
then E+ LPTR(E)
Case '—':
If EVAL(LPTR(E)) = 0
then TYPE(E) +- 6
LPTR(E) — NULL
else If EVAL(RPTR(E)) = 0
then E+ LPTR(E)
Case '+!:
If EVAL(LPTR(E)) = 0 or EVAL(RPTR(E)) = 0
then TYPE(E) + 0
pee
VALUE(RPTR(E) < 0
else If EVAL(LPTR(E)) = 1
_then E+ RPTR(E)
else If EVAL(RPTR(E)) = 1
then E+ LPTR(E)
Case ' /':
If EVAL(RPTR(E)) = 0
then Write(/ERROR: DIVISION BY ZERO’)
E + NULL
else If EVAL(LPTR(E)) = 0
then TYPE(E) — 0
VALUE(RPTR(E)) — 0
else If EVAL(RPTR(E)) = 1
then E+ LPTR(E)
Case 'f!:
If EVAL(LPTR(E))=0 and EVAL(RPTR(E))=0
then Write(/ERROR: INVALID EXPONENT’)
E «+ NULL
else If EVAL(RPTR(E)) = 1
then E+ LPTR(E)
else IfEVAL(LPTR(E)) =
EVAL(RPTR (E)) = 0
then TYPE(E) < 0
VALUE(RPTR(E)) < 1
else (handle unary operators)
If TYPE(RPTR(E)) = 0
then RESULT + -VALUE(RPTR(E))
TYPE(E) + 0
VALUE(RPTR(E)) — RESULT
4. [Finished]
Return
The algorithm for symbolic integration cannot be based on simple methods
and rules as set out in a formalized manner as in the case of symbolic
differentiation. Integration of + and — is trivial since the answer is just the
sum or difference of the integrals of the operands. For the other operators, it
would be best to try different methods of integration with some intuition as to
which one to use, until a method is found which works. This would also entail
a method of deciding when one particular method has failed. The result
would have to be checked to see if it is valid, since the result may not always
be defined. Even if we can’t find the integral, we cannot say that the
expression is non-integrable, since there are integrable expressions which
cannot be integrated symbolically.
3-30
Procedure MIN_PAREN(T,PRED_PREC). Given T, the address of a
tree expression, and PRED_PREC, the precedence of the previous operator,
this procedure prints the equivalent infix notation of that expression such that
it contains 2 minimum number of parentheses. The procedure should initially
be called with PRED_PREC = 0. This procedure assumes 2 node structure
with fields LPTR, TYPE, PRECEDENCE, and RPTR. It is also assumed
that an OPERATOR vector containing the string representations of the
operators exists, and may be indexed by operator types. Given below is a
table of the operators and their respective precedence levels.
Sto
EXERCISES SECTION 5-2.2 PAGE 392
NAME ak P
DO NZZ2ZZ22Z NDO
ELSE NZZZZZZ
NDO NELSE
GET NZZZZZZ
NDO
NELSE NGET
PUT NZZZZZZ
NDO
NELSE
NGET NPUT
THEN NZZZZZZ
NDO
NELSE
NGET
NPUT NTHEN
DECLARE NZZZZZZ
NDO NDECLARE
FIXED NZZZZZZ
NDO
NELSE
NGET NFIXED
FLOAT NZZZZZZ
NDO
NELSE
NGET
NFIXED NFLOAT
BINARY NZZZZZZ
NDO
NDECLARE NBINARY
CHARACTER NZZZZ2ZZ
NDO
NDECLARE
NBINARY NCHARACTER
BASED NZZZZZZ
NDO
NDECLARE
NBINARY NBASED
POINTER NZZZZ2ZZ
NDO
NELSE
NGET
NPUT NPOINTER
HEAD([1]
INIAAAAAES
program symtab(input,output);
ooo
var n:integer;
flag:boolean;
data,name:string;
head:header;
#include ‘length.i';
DOBBS ESSE Sn ma Ha ado a OBESE EB EB Eo rbbibonbek bic |
{ This procedure reads data from the current line in the input data until a
blank or eoln is reached, and returns the data through the parameter text. }
var ch:char;
1,J:integer;
begin
{ read data until eoin or blank is detected }
eles 2)
ele
while (ch <> ' ‘) and (i < 80) and (not eoln) do
begin
read(ch);
textfi] :== ch;
i:=i+1
end;
{ adjust cursor for blank }
ifch = !!
then i := 1-1;
{ set delimiter }
text[i] :-= ‘|’;
{ pad with blanks }
forj := i+ 1 to 80 do
text (j)o==0'!
end;
GER E ESSEC ESE E EERIE EE ICES IA EIA A HIE HEE SATIS IA EES HE 4 & }
function create:ptr;
{ This function sets up a head node for a new block level and returns a
pointer to the head node. }
var p:ptr;
5-34
begin
new(p);
pt-symbols := 'ZZZZZ2Z|';
pt.info := 'HEAD|';
pf.Iptr := nil;
pft.rptr := nil;
create := p
end;
{ This procedure inserts or searches for name in the symbol table according to
the value of the boolean variable insert. }
var parent,t,p:ptr;
begin
{ initializations }
t := head[n];
{ search for name }
while t <> nil do
begin
{ compare given item with node }
if name < tf.symbols
then begin
parent := t;
t:== tf.Iptr;
if t = nil
then if insert
then begin
{ create leaf node and insert it }
new(p);
pt.symbols := name;
pt.info := data;
pft.Iptr := nil;
pt.rptr := nil;
parentf.Iptr := p;
table := true
end
else table := false
end
else if name > tf.symbols
then begin
5735
parent := t;
t :=t]irptr;
if t = nil
then if insert
then begin
new(p);
pt.symbols := name;
pt.info := data;
pt.lptr := nil;
pt.rptr := nil;
parent{.rptr := p;
table := true
end
else table := false
end
else begin
if insert
then table := false
else begin
table := true;
data := tf.info
end;
t := nil
end
end
end;
FEE E EEE SEES EESSE ES SOE ERIE TES EE EEE IEE EE EE)
procedure inord(t:ptr);
begin
{ check for null pointer }
if t <> nil
then begin
{ traverse left subtree }
inord(tf.Iptr);
{ print contents of node }
writeln(/ NODE: ':7,tt.symbols:length(tt.symbols),! ':2,
tt.info:length(tt .info));
{ traverse right subtree }
inord(tt.rptr)
end
end;
Br 36
SESE OSE EEEEEE GEESE EAI A SATIS}
GeO EEE E REED EERE SEEDEE
begin
{ process all data }
while not eof do
begin
{ read data }
get(name);
get(data);
readin(n, flag);
{ initialize head node if necessary }
if head[n] = nil
then head[n] := create;
{ handle insertion/search }
if flag .
then if table(n,flag,name,data)
then begin
writeln;
writeln(‘INSERTION SUCCESSFUL’);
writeln(/ NAME = ‘,name:length(name));
writeln(/DATA = ' data:length(data))
end
else begin
writeln;
writeln(/ MULTIPLE INSERTION UNSUCCESSFUL’);
writeln(/NAME = ' name:length(name));
writeln('DATA = ' data:length(data))
end
else if table(n,flag,name,data)
then begin
writeln;
writeln(/'SEARCH SUCCESSFUL’};
writeln(/ NAME = ‘ name:length(name));
writeln(’DATA = 'data:length(data))
end
else begin
writeln;
writeln(/SEARCH UNSUCCESSFUL’);
writeln(/NAME = ' name:length(name))
end
end;
{ traverse tree in inorder to assure program correctness }
writeln;
writeln;
writeln(/INORDER TRAVERSAL! );
inord(head{1])
end.
DO KEYWORD 1 true
ELSE KEYWORD 1 true
GET KEYWORD 1 true
PUT KEYWORD 1true
THEN KEYWORD 1 true
DO KEYWORD 1 true
DECLARE KEYWORD 1 true
FIXED KEYWORD 1true
FLOAT KEYWORD 1 true
BINARY KEYWORD 1true
CHARACTER KEYWORD 1true
BASED KEYWORD 1true
DO KEYWORD 1 false
POINTER KEYWORD 1true
IF KEYWORD 1false
RESULTS:
INSERTION SUCCESSFUL
NAME = DO
DATA = KEYWORD
INSERTION SUCCESSFUL
NAME = ELSE
DATA = KEYWORD
INSERTION SUCCESSFUL
NAME = GET
DATA = KEYWORD
INSERTION SUCCESSFUL
NAME = PUT
DATA = KEYWORD
INSERTION SUCCESSFUL
NAME = THEN
DATA = KEYWORD
5-38
MULTIPLE INSERTION UNSUCCESSFUL
NAME = DO
DATA = KEYWORD
INSERTION SUCCESSFUL
NAME = DECLARE
DATA = KEYWORD
INSERTION SUCCESSFUL
NAME = FIXED
DATA = KEYWORD
INSERTION SUCCESSFUL
NAME = FLOAT
DATA = KEYWORD
INSERTION SUCCESSFUL
NAME = BINARY
DATA = KEYWORD
INSERTION SUCCESSFUL
NAME = CHARACTER
DATA = KEYWORD
INSERTION SUCCESSFUL
NAME = BASED
DATA = KEYWORD
SEARCH SUCCESSFUL
NAME = DO
DATA = KEYWORD
INSERTION SUCCESSFUL
NAME = POINTER
DATA = KEYWORD
SEARCH UNSUCCESSFUL
NAME = IF
INORDER TRAVERSAL
NODE: BASED KEYWORD
NODE: BINARY KEYWORD
NODE: CHARACTER KEYWORD
NODE: DECLARE KEYWORD
Dg
NODE: DO KEYWORD
NODE: ELSE KEYWORD
NODE: FIXED KEYWORD
NODE: FLOAT KEYWORD
NODE: GET KEYWORD
NODE: POINTER KEYWORD
NODE: PUT KEYWORD
NODE: THEN KEYWORD
NODE: ZZZZZZ HEAD
5-40
<Ob> tO | eC
oe Corer aC ee
=> i+ <e>* <e>
=>i+i* <e>
—>iti*i
<C> SG a KO
<6 > 1c * eS
le <6 > ee
i+ti* <e>
Vddyd
i+i*1
So
<e> ms <e> <e> ~
1 i i i
5-41
check for +. Yes. CURSOR ~ 3
check for #. No.
Call EXPR
Call TERM
Call FACTOR
check for #. No.
check for (. No.
check for i. Yes. CURSOR < 4.
Return true from FACTOR.
check for *. Yes. CURSOR + 5.
check for #. No.
Call TERM
Call FACTOR
check for #. No.
check for (. No.
check for 1. Yes. CURSOR + 6.
Return true from FACTOR.
Check for *. No.
Return true from TERM.
Return true from TERM.
Check for +. No.
Return true from EXPR.
Return true from EXPR.
Check for #. Yes. CURSOR + 7.
WWWWWwW
RW Return VALID from Main.
TRADPDNADAAAMMAANAANANA
WP
b) CURSOR ACTIVITY
Perform Main
Call EXPR
Call TERM
Call FACTOR
check for #. No.
check for (. No.
check for i. Yes. CURSOR + 2.
Return true from FACTOR.
Check for *. No.
Return true from TERM.
Check for +. Yes. CURSOR + 3.
Check for #. No.
Call EXPR
Call TERM
Call FACTOR
check for #. No.
eS
Bee
B&B
SB
&
HDHD
WWwWwwWWWWNHNH check for (. Yes. CURSOR + 4.
5-42
check for #. No.
Call EXPR
Call TERM
Call FACTOR
check for #. No.
check for (. No.
check for i. Yes. CURSOR + 5.
Return true from FACTOR.
check for *. No.
Return true from TERM.
check for +. Yes. CURSOR + 6.
check for #. No.
Call EXPR
Call TERM
Call FACTOR
check for #. No.
check for (. No.
check for i. Yes. CURSOR + 7.
Return true from FACTOR.
check for *. No.
Return true from TERM.
Check for +. No.
Return true from EXPR.
Check for +. No.
Return true from EXPR.
Check for ). Yes. CURSOR + 8.
Return true from FACTOR.
Check for *. No.
Return true from TERM.
Check for +. No.
Return true from EXPR.
Return true from EXPR.
Check for #. Yes. CURSOR + 9
RRR
HH
BRK
ANAM
AMAAAMAA
MAA Return VALID from Main.
OWWWWMmMAANANNNNTWNTWN
5-43
check for *. Yes. CURSOR + 3.
check for #. No.
Call TERM .
Call FACTOR
check for #. No.
check for (. Yes. CURSOR + 4.
check for #. No.
Call EXPR
Call TERM
Call FACTOR
check for #. No.
check for (. No.
check for i. Yes. CURSOR + 5.
Return true from FACTOR.
check for *. No.
Return true from TERM.
check for +. Yes. CURSOR + 6.
check for #. No.
Call EXPR
Call TERM
Call FACTOR
check for #. No.
check for (. No.
check for i. Yes. CURSOR + 7.
Return true from FACTOR.
check for *. No.
Return true from TERM.
check for +. No.
Return true from EXPR.
Return true from EXPR.
check for ). Yes. CURSOR + 8.
Return true from FACTOR.
check for *. No.
Return true from TERM.
Return true from TERM.
check for +. No.
Return true from EXPR.
check for #. Yes. CURSOR + 9
Sy
eel
AY
SK
AR
BONN
D008
00:00
PB
Pep
Gh
onli
Chey.
Misi
CATES
On
SSee
ea
ae Return VALID from Main.
ee
3) < expr > u= < term > + < expr > | < term > - < expr >|< term >
< term > u== < factor > * < term > | < factor > / < term> |
< factor >
< factor > = @ < major > | < major >
5- hh
< major > < minor > t < major > | < minor > | @ < major >
< minor > ::= (< expr >) |i
program recdsnt(input,output);
{ This program is similar to the algorithm of the same name from the text,
except that two extra recursive procedures are required to handle the extra
operators. The variables are the same as those used in the text. Note that %
is used to denote exponentiation and that @ is used for the unary minus. }
#include ‘getline.i';
#include ‘length.i’;
GABE ESSE SAHA EE EE SE EGC E EASE A CIA IIE HEE AS }
procedure scan;
{ This procedure gets the next input character from the indat string, and
updates relevant global variables. }
begin
next := indat[cursor];
cursor := cursor + 1
end;
[ABBE EEE OBESE E ESAS EAHA AES ECEES OSOBOE AOE EEE}
function expr:boolean; forward;
ABBE BAHAB SES SSOHnoHa Had HrdHbd bn badHEobrdor bndbnlblibicbiiicr}
function minor:boolean;
begin
if next = ‘7’
then minor := false
else if next = ‘('
then begin ‘
scan;
5-45
if not expr
then minor := false
else if next <> ')!
then minor := false
else begin
scan;
minor := true
end
end
else if next <> 'i!
then minor := false
else begin
scan;
minor := true
end
end;
functicn major:boolean;
begin
if next = '@!
then begin
scan;
if next = '#!
then major := false
else if not major
then major := false
else major := true
end
else if minor
then if next = '%!
then begin
scan;
if mext qi #!
then major := false
else if not major
then major := false
else major := true
end
else major := true
else major := false
end;
5-46
FEB CHEEBE HEEB EAHA EOE ESSE EASES ECCS EEE EE EES EA EAE }
function factor:boolean;
begin
if next = 'Q!
then scan;
if next = '#!
then factor := false
else if not major
then factor := false
else factor := true
end;
function term:boolean;
begin
if not factor
then term := false
else if (next = '*’) or (next = '/')
then begin
scan;
if next = '#!
then term := false
else if not term
then term := false
else term := true
end
else term := true
end;
DEBE B EBB B
BREE EERE BHO E SABE BEEE ECG E CBSO E ESSERE EE bee}
function expr;
{ This function checks for term +/— expr and returns false if it is neither of
these. }
5-47
begin
if not term
then expr := false
else if (next = ‘+‘) or (next = ‘~')
then begin
scan;
if next = '#!
then expr := false
else if not expr
then expr := false
else expr := true
end
else expr := true
end;
Salada
begin
{ engage loop to process all input }
while not eof do
begin
- getline(indat);
cursor := 1;
scan;
if (expr) and (next = '#')
then writeln('VALID = ‘:10,indat:length(indat))
else writeln(/INVALID ':10,indat:length(indat))
end
end.
VALID i+1*i#f
INVALID i+#¢
VALID i*(i*i)#
VALID i/(i+i-i*i)#
VALID ((i+i))#
INVALID __ (((i+i)/i)#
INVALID _ #i/(i+i)#
VALID (@i+i)% (i-i)*(i+i*i)#
VALID i+(i+i)#
VALID @i#
5-48
4) Modifications to function EXPR to include the subtraction operator:
5-49
then Return(false)
Return(SUB_EXP)
Procedure SCAN. This procedure places the next character of INPUT into
NEXT. If CURSOR ever goes beyond the length of INPUT, and error has
occurred.
1. [Remove character]
NEXT + SUB(INPUT,CURSOR,1)
CURSOR + CURSOR + 1
2. [Check for error] \
If CURSOR > LENGTH(INPUT)
then Write("ERROR: CURSOR PAST LENGTH OF STRING’)
Exit
else Return
1. [Return character]
CURSOR + CURSOR - 1
NEXT + SUB(INPUT,CURSOR - 1,1)
Return
cg
EXERCISES SECTION 5-3.1 PAGE 411
1) M=6,R= 10,5=9
STEP| I J K | T |CROW|I] |AMAX|BMAX |SUM| C/T] |COLUMN |CCOL|T
eae O
3 ;
1 1 0 0
3 3
a 6
8
7 to 4
8
7 9
8
9
5 1
8
9
10 |2
3 5 0 0
fi 4
6 11
8 11
9
5 7
8
5 8
8
5 4
8
9
10 |3
3 9 0 0
8 4
5 10
8 10
9
10 |4
3 10 0 0
9 ts
7 6
8 10
6 19
8 11 19
9
5 8
8 12
DAeAHAaS
Kon
RESULTING STRUCTURES:
CROW CCOL
10
13 ud 11
15
10
10 10
ot 1] 19
12 12
13 13 20
14 14
15 15
16 16
17 17
ae
program matadd(input,output);
const m = 4;
r= 8;
s = 10;
q = 18;
begin
{ read in arrays a and b }
for i :-= 1 to m do
readIn(arow{i] ,brow[{i]);
for i:= 1tordo
~ readIn(acolfi,
a[i]);
for i:=1tosdo
readIn(bcol[i],b[i]);
{ initializations }
Less 1:
t := 0;
{ scan each row }
while i <= mdo
begin
{ obtain row indices and starting position of next rows }
j := arow|il;
k := brow|il;
crow|i] := t + 1;
amax := 0;
bmax:= 0;
ifi<m
then begin
p:=i+1;
while (amax = 0) and (p <= m) do
begin
amax := arow(p];
p:=p+l
end;
p:=i1+ 1;
5-54
while (bmax = 0) and (p <= m) do
begin
bmax := brow|p];
p:=pt+1
end
end;
if amax = 0
then amax := r+ 1;
if bmax = 0
then bmax :=s + 1;
{ scan columns of this row }
while (j <> 0) and (k <> 0) do
begin
{ elements in same column? }
if acol[j] = bcol[k]
then begin
sum := alj] + blk];
column := acol{j];
j:=jt+)
k:=k-+1
end
else if acol{j] < bcol[k]
then begin
sum := aj];
column := acollj];
j:=jt+l
end
else begin
sum := b|k];
column := bcol|k];
k:=k+1
end;
{ add new elements to sum of matrices }
ifsum <> 0
then begin
<==t+1;
c[t] := sum;
ccol{t] := column
end;
{ end of either row? }
if) = amax
then j := 0;
ifk = bmax
then k := 0;
end;
ohne
{ add remaining elements of row }
if (j = 0) and (k <> 0)
then while k < bmax do
begin
t:=t+15
c(t] <== blk];
ecollt] := bcol|k];
k:=k+1
end
else if (k = 0) and (j <> 0)
then whilej < amax do
begin
t:=t4+1;
c[t] := alj];
ccol{t] := acollj];
J:=j+1
end;
{ adjust index to matrix C and increment row index }
ift < crow|i]
then crow[i] := 0;
1:=1+ 1;
end;
{ verification }
writeln;
writeln(’ AROW VECTOR'’:19);
for 1 := 1 tom
do
writeln(i:4,arow(i]:11);
writeln;
writeln(' ACOL VECTOR A!:28);
for i:= 1 tordo
writeln(i:4,acol[i]:11,a[i]:13);
writeln;
writeln(' BROW VECTOR':19);
for i:=
1 to mdo
writeln(i:4,brow[i]:11);
writeln;
writeln(' BCOL VECTOR B!:28);
for i:= 1 tos do
writeln(i:4,bcol[i}:11,b[i}:13);
writeln;
writeln(’ == CROW VECTOR’:19);
for i := 1 to m do
writeln(i:4,crow(i]:11);
writeln;
writeln(' CCOL VECTOR C’:28);
5-56
for
i := 1 to
q do
writeln(i:4,ccol|i]:11,c[i]:13)
end.
AROW VECTOR
1
AaAnkr
WD w
oHown
—
a
NA
SOMNHA
WHE
_ he
A
NPRWORN
AWNnNOoORONNOOD
BROW VECTOR
Dm
Wh
ne re
ow
ork
BCOL VECTOR
KE
WD
OSOOntnanFF
Re
PWN
ane
NP
Sea]
CROW VECTOR
1 1
2 5
3 9
4 10
‘8 13
6 15
CCOL VECTOR C
1 3 6
Z 4 4
3 5 9
4 L 1
5 1 11
6 4 ¢
7 5 8
8 7 4
9 1 10
10 Z 6
11 3 19
12 4 8
13 I 20
14 rf 2
15 4 3
16 5 1
ug 7 5
18 0 0
19 0 0
program conmat(input,output);
const m = 10;
n 10;
type ptr = {matel;
matel = record
left:ptr;
up:ptr;
v:integer;
r:integer;
c:integer
end;
br 56
var row,column,value:integer;
arow:array([1..m] of ptr;
acol:array[1..n] of ptr;
p,q,temp:ptr;
i:integer;
begin
{ initialize matrix structure }
for i := 1 to mdo
begin
new(p);
pft.c := 0;
pt.left := p;
arow|i] := p
end;
for i:= 1tondo
begin
new(p);
pft.r := 0;
pt.up := p;
acolli] := p
end;
{ obtain information for matrix elements and insert them }
while not eof do
begin
readIn(row,column,value);
{ allocate and initialize node }
new(p);
p{.t := row;
pft.c := column;
pt.v := value;
{ find new node's position in row list }
q := arow(pt.rl;
temp := qf.left;
while pf.c < tempf.c do
begin
q := qf.left;
temp := qf.left
end;
pt.left := temp;
qt.left := p;
{ find new node's position in column list }
q := acoll[pt.c];
temp := qf.up;
§2oa
while pf.r < temp{.r do
begin
q := qt.up;
temp := qf.up
end;
pf.up := temp;
qf.up := q
end
end.
A B
Ve tbe tee: Bane. PRODUCT
Sipe. Ss Sete ot 0
20 Oe ed { 180
Ora th2S Gera ee
ie Sa?
Grieg dF 33
0
Oe tee es at3
LOetcne haucs
0
5-60
20
AN 20
180
N
rt
N
~~
iD
lo)
x
<x
ft
co NN 56
4 64
16
Orn
NNN
18
rote
ws ComN
NANNN
etc.
. 61
Algorithm MATRIX_MULTIPLICATION. Given sparse matrices A
and B represented by vectors A and B with row and column indices AROW
and ACOL, BROW and BCOL respectively, this algorithm forms the matrix
product C = A X B. A has dimensions M X T and B has dimensions
SX
N, therefore C will have dimensions M x N. A has R non-zero elements
and
B/has S non-zero elements.
1. [Initializations]
L+0O
2. [Scan all rows of A]
Repeat thru step 5 for] = 1, 2, ..., M
3. [Determine beginning of rows.]
CROW[L] —L +1
P + AROWII]
AMAX «+ O
Repeat for Z = 1+ 1,1 + 2, ..., M while AMAX = 0
AMAX ~— AROW(Z]
If AMAX = 0
then AMAX+R+1
4. [Scan all columns of B]
IfP 340
‘then’ Repeat for J = 1, 2, ..., T
PRODUCT + 0
(Scan thru all row/column entries)
Repeat for K = P, P + 1, .... AMAX - 1
COL + ACOLIK]
Q + BROW|COL]
BMAX + 0
Repeat for Z = COL + 1, COL + 2, ..., T while BMAX = 0
BMAX + BROW|Z]
If BMAX = 0
then BMAX +S+1
O40
then Repeat while Q < BMAX and BCOL[Q] < J
Q<-Q+1
If BCOL[Q] = J
then PRODUCT — PRODUCT + A{J] * B[Q]
If PRODUCT + 0
then L+L+1
C[L] — PRODUCT
CCOLIL] + J
5. [Adjust row vector if necessary]
If T < CROW|]]
then CROWJ|I] — 0
6. [Finished]
Exit
5>62
5) Algorithm MATRIX_ADDITION. Given pointer arrays AROW, ACOL,
BROW, and BCOL pointing to multi-linked representations of sparse matrices
A and B with dimension M X N, this algor!:hm forms the representation of
the sum matrix C = A + B. Pointer arrays CROW and CCOL are used to
point to rows and columns of matrix C which also has dimension M XN.
5-64
EXERCISES SECTION 5-3.2 PAGE 421
5-65
then PGLINK(Q) + T
else PAGEPTR + T
PGLINK(T) — R
else If TEMP1 < PGNO1(R)
then PGNO1(P) + TEMP1
else If TEMP2 > PGNO2(R)
then Q + PGLINK(R)
eit
FOUND + false
Repeat while Q 4 NULL and ~FOUND
If PGNO1(Q) > TEMP2
then FOUND < true
else T+ Q
1. [Initializations]
PAGE +"!
SAVE + PAGEPTR
2. [Scan linear list]
Repeat thru step 5 while SAVE of NULL
3. [Add first page number to string.|
TEMP «+ PGNO1(SAVE)
KEEP «+ PGNO2(SAVE)
PAGES + PAGES 0 ',! 0 TEMP
4. [Search for range of numbers]
SAVE + PGLINK(SAVE)
FOUND + false
Repeat while SAVE NULL and -FOUND
If PGNO1(SAVE) 4 KEEP + 1
then FOUND < true
else KEEP «+ PGNO2(SAVE)
SAVE + PGLINK(SAVE)
5-66
5. [Add range if there is one]
If FOUND
then PAGES + PAGES 0 '-! 0 KEEP
6. [Finished]
Return(PAGES)
1. [Initializations]
FIRSTMJ + NULL
2. [Loop until input is exhausted]
Repeat thru step 8 until input is exhausted
3. [Input next input term string]
Read(STRING)
4. {Locate special symbols]
A + INDEX(STRING,’'#')
B + INDEX(STRING,'%')
C + INDEX(STRING,'@’)
5. [Obtain page numbers]
fc +0
then PAGES + SUB(STRING,C+1)
STRING + SUB(STRING,1,B-1)
else PAGES + /
6. [Obtain the sub2term]
IfB 0
then SUB2TERM + SUB(STRING,B+1)
STRING — SUB(STRING,1,B-1)
else SUBTERM + ”!
7. [Obtain the subterm]
IA 20
then SUBTERM + SUB(STRING,A+1)
STRING + SUB(1,A-1)
else SUBTERM + "
8. [Obtain major term]
If STRING 4"
then MAJORTERM + STRING
T + FIRSTMJ
it = "NOLe
then FIRSTMJ «+ SAVE + ALLOCATE_MJ(MAJORTERM)
else FOUND + false |
Repeat while AFOUND
5-67
If MAJORTERM < TERM(T)
then If LPTR(T) = NULL
then LPTR(T) + SAVE +
ALLOCATE_MJ(MAJORTERM)
FOUND + true
else“ "T' = EPTR(T)":
else If MAJORTERM > TERM(T)
then If RPTR(T) = NULL
then RPTR(T) + SAVE
FOUND + true
else R + RPTR(T)
else SAVE + T
FOUND + true
(update subterm and page number lists)
If SUBTERM + "'
then Call INSERT(SUBLIST(SAVE),SUBTERM,PAGES)
else Call PAGING(MJPAGE(SAVE),PAGES)
9. [Finished]
Exit
1)
Ee
Oe=©
oo
locoo [ee
ee
|
2) (I+ AJA(I+A)=(IAI
+ (IAA) + (AAD +(AAA)=I4A4 A
(since A+ A = A.)
Assume (I+ A)» eat TSE AS es A
Then ([+A) = (I + A)® (14 A)
=(I+A--- ae + A)
=I+A+::: Af ee + AM
=I+A+4+--- +A
5-69
3) P=I1+A+A@4 --- 4A
= (14
Maj
4) A= Oo culses 0) 0oo00
0-0. OF 10
SOs SOON CO
Ot Ok
Gro ch “O26
Ae OI Yh QT any.
Oe TQ tat Of
fea ONE My Mele]
OPO ey rey
Ona ts nO? weds cy
d = Gow oh
oo 0 1 1
SONS yOu es A
Sone 2, 0
At=A+A®+4
A® + AM
dy = 1iff <Vi,Vj> € E
dj; = oo if v; is not reachable from vy,
1. [Initializations]
C+B
PATH+ P+”
2-70
to [Perform a pass|
Repeat thru step 5 fork = 1, 2,..., N
3. [Process rows|
Repeat thru step 5 fori = 1, 2,..., N
4. [Process columns]
Repeat thru step 5 forj = 1, 2, ..., N
5. [Save first branch of minimal paths]
If Ci, ap Cy <i Cy
then Cy -— Cy + Cy
Py - CONVERTCHAR(K) © i!
else If Cy + Cy = Cy
then Py + Py © CONVERTCHAR(K) © '+!
6. [Creat array of all minimal paths]
Repeat for i = 1, 2,..., N
Repeat forj = 1, 2, ...,N
Write(PATHSTRING(C,P,,i,j))
et [Finished]
Exit.
then Return(PATH,))
2. [Path between adjacent nodes?]
If Cj = 1
then Cy + Nf 2
PATHy + Ly
Return(PATHy i)
3. [One branch in minimal path?
T + INDEX(P;;,'+')
k — CONVERTNUM(SUB(P;;,1,T — 1))
PATH; + Se 0 PATHSTRING(k,j)
If T = "LENGTH(Py)
then Return(PATH,))
4. [Several branches]
Repeat while T A LENGTH(P,)
Py; — SUB(P,;,T + 1)
T + INDEX(P,;,’+’)
STi
k — CONVERTNUM(SUB(,,1,t 1))
PATH, + PATH, © ',’ © PATHSTRING(i,k) © PATHSTRING(k,j)
Return('(' © PATH, © ')!)
6) program minpaths(input,output);
{ Given a digraph with all its edges labeled, this program displays all
minimum paths between all pairs of nodes. The input is an adjacency matrix
and corresponding label matrix. The output is a path matrix where each
entry contains all minimum paths for a pair of nodes. }
const n = 7;
FE EEE AEA BEEBE AEE OEE ASAE BIO AEE S444 64 44}
#include ‘length.i’;
#include 'index.i’;
#include 'sub.i’;
#include ‘concat.i';
(OBES Baar onddcicianiaa Hiei iidenniiddibiiniieineiaiiiocccionr)
function cnum(str:string):integer;
var n,c,l:integer;
temp:string;
begin
n := 0;
c:= 1;
] := length(str);
while (c <= 1) do
begin
sub(str,c,1,temp);
n := 10 * n + index('0123456789|'
temp) — 1;
ci=c+#A
end;
oe
chum :=n
end;
GABE B BEES SEE EEE SESE ESBS AROSE EEE ESB OBB B AB SABE EE EE EE}
function cchar(int:integer):string;
var i,r,d:integer;
c,temp:string;
begin
re — sl:
if int > 0
then d := int
else d := 0;
while d <> 0do
begin
r:= d mod 10;
d'=— a div 10:
sub('0123456789' ,r+1,1,temp);
ci] := temp[]];
i:=i+1
end;
{ add string delimiter }
Clile== IV;
cchar :=c
end;
[ABBE RBBB EEE BSB BEEBE EEE AHO SSEES SSH BSS EBEBE oes)
function pathstring(i,j:integer):string;
{ Given two nodes, the previously described temporary matrices, and the label
matrix, this function calculates all minimum paths between the nodes and
stores them in character type in the path matrix. A string of one blank
implies no path exists. }
var t,k:integer;
temp,temp1,temp2:string;
begin
{ check for previously determined path }
if c[i,j] = n*n
ato
then pathstring := pathii,j]
else { check for path between adjacent nodes }
if cli,j] = 1 |
then begin
c[i,j] := u*n;
path[i,j] := i,j];
pathstring := patb[i,}]
end
else begin
{ check for one branch in minimal path }
cfi,j] := n*n;
t := index(pji,j],’+|’);
sub(pli,j],1,t-1,temp);
k := cnum(temp);
concat({pathstring(i,k),pathstring(k,j),path{i,j]);
if t = length(pli,j])
then pathstring := pathii,j]
else begin
{ several branches }
while (t <> length(p|i,j])) do
begin
sub(p[i,j],t+1,length(p[i,j])+,
p[i,i]);
t := index(pli,j],’+|’);
sub(p|i,j],1,t-1,temp);
k := cnum(temp);
concat(path|i,j],’,|',temp1);
concat(pathstring(i,k),pathstring(k,j),temp2);
concat(temp1,temp2,path|i,j})
end;
concat('(|' path[i,j],path{i,j]);
concat(path{i,j],’)|',path{i,j]);
pathstring := pathii,j]
end
end
end;
begin
{ read adjacency and label matrices }
for i:= 1 tondo
begin
for j := 1 ton do
begin
read(b[i,j]);
5-74
if bli,j] = 0
then b[i,j] := n*n
else begin
read(temp[1));
temp[2] := '|';
[i,j] := temp
end
end;
readin
end;
{ compute minimum paths }
Crp:
for k := 1 tondo
begin
for i:= 1 to n-do
begin
for j}:= 1tondo
begin
if cli,k] + clk,j] < c[i,j]
then begin
c{i,j] := c[i,k] + c[k,j];
concat(cchar(k),’+|',p[i,j])
end
else if c{i,k] + c[k,j] = c[i,j]
then begin
concat(p[i,j],cchar(k),temp);
concat(temp,’
+| ,p[i,j])
end
end
end
end;
{ output results }
for i := 1 tondo
begin
forj := 1tondo
begin
result := pathstring(i,j);
writeln(/ MINPATH(':8,i:1,!,/:1,j:1,') = ':4,result:length(result))
end
end
end.
or]
0 la 1lbO0000
000 le 00 0
00 1k 1d 000
1 770.020 leoit.0
0 0 0 0 1
0 0 0 0 1
00 aost
oe - 00
a O° 0a
©=
MINPATH(1,1)
MINPATH(1,2)
MINPATH(1,3)
MINPATH(1,4)
MINPATH(1,5)
MINPATH(1,6)
MINPATH(1,7) ((ac,bd)eg,(ac,bd)fh)
MINPATH(2,1) cj
MINPATH(2,2) cja
MINPATH(2,3) cjb
MINPATH(2,4) c
MINPATH(2,5) ce
MINPATH(2,6) | cf
MINPATH(2,7) (ceg,cfh)
MINPATH(3,1 ) dj
MINPATH(3,2 ) dja
MINPATH(3,3 ) k
5-7/6
d
I de
df
(deg, dfh)
I J
ja
I jb 7
(jac,jbd,(eg,fh)i)
e
I f
(eg,fh)
gi)
gia
gijb
gi
gie
gif
g
hij
hija
hijb
hi
hie
hif
h
iJ
I ija
ijb
i
!| le
if
I (ieg,ifh)
EXERCISES SECTION 5-4.2 PAGE 444
1. [Valid arguments?]
If A = NULL or B = NULL
then Write(/ERROR: NULL ARGUMENT(S)')
Return(false)
2. [Determine equality]
If DPTR(A) = DPTR(B)
then Return(true)
else Return(false)
5-78
4) Function UNION(X,Y). Given X and Y, head nodes pointing to two list
structures, this function returns the address of the head node of the list which
is the union of X and Y. Algorithms HEAD, TAIL, CONSTRUCT and
MEMBER are used in this recursive function.
1. [Valid lists?]
If X = NULL or Y = NULL
then Write(/ERROR: NULL ARGUMENT(S)')
Return(NULL)
2. [Trivial case?
If RPTR(X) = NULL
then Return(Y)
else If RPTR(Y) = NULL
then Return(X)
3. [Recursive calls]
If MEMBER(HEAD(X),Y)
then Return(UNION(TAIL(X),Y))
else Return(CONSTRUCT(HEAD(X),UNION(TAIL(X),Y)))
1. [Valid lists?]
If X = NULL or Y = NULL
then Write(/ERROR: NULL ARGUMENT(S)’)
Return(NULL)
2. [Trivial case?]
If RPTR(X) = NULL
then Return(X)
else If RPTR(Y) = NULL
then Return(Y)
3. [Recursive calls]
If MEMBER(HEAD(X),Y)
then Return(CONSTRUCT(HEAD(X),INTER(TAIL(X),Y)))
else Return(INTER(TAIL(X),Y))
ee
ee
1. [A and/or B atoms?|
If ATOM(A) = 1
then RETURN(EQ(A,B))
else If ATOM(B) = 1
then Return(false)
2. [Neither are atoms]
If EQUAL(HEAD(A), HEAD(B))
then Return(EQUAL(TAIL(A),TAIL(B)))
1. [Initializations]
P — NULL
2. [Add successive elements of A to front of new list]
Repeat while A 4 NULL
P + CONS(REVERSE(CAR(A)),P)
A + CDR(A)
3. [Finished]
Return(P)
5-80
1. [Check for valid entries.
If P = NULL or Q’'= NULL
then Return(0)
2. [Check for empty list]
If RPTR(P) = NULL and DPTR(P) = NULL
then Return(0)
3. [Traverse to right of list]
A + RPTR(P)
FOUND + false
Repeat while A 54 NULL and -FOUND
If ATOM(A) = 1
then Ao
then FOUND + true
POSS — 0
else If DPTR(A) 4 NULL
then POSS + LEVEL(DPTR(A),Q)
IEOSs 0
then FOUND + true
A + RPTR(A) .
4. [Check if node found]
If FOUND
then Return(POSS + 1)
else Return(0)
5-6
8) Procedure PRINTOUT(L). Given L, a pointer to a list header node, this
procedure invokes a procedure PRINT to print out the parenthesized
expression corresponding to the list, structure.
1. [Initializations]
MAX + 0
2. [Check for null pointer}
Iv Se== NULL
then Return(MAX)
3. [Scan through list to the right]
P+S
5-82
Repeat while P 4 NULL
If ATOM(P) = 1
then ANS <0
else ANS «+ DEPTH(DPTR(P))
If ANS > MAX
then MAX + ANS
P + RPTR(P)
4, [Add this level]
MAX + MAX + 1
5. [Finished]
Return(MAX)
ie [Initializations]
ANS + false
De [Check for null pointers]
If S = NULL and T = NULL
then Return(true)
[Compare lists]
If S 4 NULL and T 4 NULL
then If ATOM(S) = ATOM(T)
then If ATOM(S)= 1
then If VALUE(DPTR(S)) = VALUE(DPTR(T))
then ANS + true
else ANS + EQUAL(DPTR(S),DPTR(T))
If ANS
then ANS + EQUAL(RPTR(S),RPTR(T))
[Finished]
Return(ANS)
EXERCISES SECTION 5-4.3 PAGE 448
[2| 14 |
Septal eeee
Pu Ale oa
UE eae
5-84
Algcrithm CONSTRUCT_LIST. This algorithm reads pairs of directed
edges representing a graph, thus creating an adjacency list structure. The node
structure from the text is assumed.
L, [Initialize structure]
Repeat for l= 1, 2; ..., N
LINK{I]
— NULL
[Engage loop to process all data]
Repeat thru step 5 while there remains data
[Read next pair of edges]
Read(X,Y)
[Allocate and initialize new node]
Q — NODE
DESTIN(Q)—Y
EDGEPTR(Q)
— NULL
[Insert node into appropriate list]
PRED + NULL
SUCC
+ LINK[X]
FOUND + false
Repeat while SUCC 4 NULL and -FOUND
If DESTIN(SUCC) > Y
then FOUND + true
else PRED «+ SUCC
SUCC + EDGEPTR(SUCC)
EDGEPTR(Q)
—SUCC °
If PRED. => NULL
then LINK[X]
—Q
else EDGEPTR(PRED)
«Q
6. [Finished]
Exit
5295
DESTIN(Q) + j
EDGEPTR(Q) + NULL
PRED «+ NULL ~
SUCC + LINK{i] —
FOUND ~+ false
Repeat while SUCC $4 NULL and 7 FOUND
If DESTIN(SUCC) > j
then FOUND < true
else PRED «+ SUCC
SUCC + EDGEPTR(SUCC)
EDGEPTR(Q) + SUCC
If PRED = NULL
then LINK[{i] — Q
else EDGEPTR(PRED) + Q
5.
3 4
Pee Le
REACH | NODE NO | DATA | DIST | LISTPTR
een er
eases
pee
as ate VY
ence or
2 IFA TOY,
ee ee ey
Pern Sea" | ETHER-ED
3) Function CONNECTED. This function is the same as procedure BFS in
the text, with the exception that a check is made to determine if the graph is
connected or not. The function returns true is the graph is connected; false
otherwise.
1. [Initialize the first node's DIST number and place node in queue]
REACH{INDEX] + true
DIST{INDEX] + 0
Call QINSERT(QUEUE,INDEX)
2. [Repeat until all nodes have been examined]
Repeat thru step 5 while queue is not empty
3. [Remove current node to be examined from queue]
Call QDELETE(QUEUE, INDEX)
4. [Find all unlabeled nodes adjacent to current node]
LINK «— LISTPTR[INDEX]
Repeat step 5 while LINK 4 NULL
5. [If this is an unvisited node, label it and add it to the queue]
If -REACH|DESTIN(LINK)]
then DIST|DEST(LINK)] — DIST[INDEX] + 1
REACH[DEST(LINK)] + true
Call QINSERT(QUEUE, DESTIN(LINK))
LINK +- EDGEPTR(LINK) (Move down edge list)
6. [Determine if graph is connected]
CONNECT + true
Repeat for I = 1, 2, ..., N while CONNECT
If DIST{I] = 0
then CONNECT + false
7. [Finished]
Return(CONNECT)
EXERCISES SECTION 5-4.5
Seer eee
Pe teal aceon
fpedrme:| oesepeatmiesee
ivetly conan |
pites|Sea)
bre
5-88
Procedure LOW_MAIN(N). This procedure is the top-level procedure for
determining the cutvertices and lowpoints of an N-node graph. Most of the
work is done by the procedure LOW_COMPUTE. The graph is represented
using the node and edge structures described in the text. COUNT keeps track
of the DFN numbers. There are a number of N-element arrays: DIN holds
node’s DFN number; REACH keeps track of whether the node has been
visited; LOW holds a node’s lowpoint number; PARENT contains a node’s
parent in the constructed tree; CUTVERT indicates whether a node is a
cutpoint. The desired results are contained in LOW and CUTVERT upon
return.
1. [Initializations]
Repeat for J = 17.235.4'N
REACH|I] < false
CUTVERT|I] + false
2. [Comput lowpoiuts and cutvertices]
COUNT + 0
Call LOW_COMPUTE(COUNT)
3. [Finished]
Return
1. [Mark node] :
COUNT «+ COUNT + 1
DFN{INDEX] + COUNT
LOW(INDEX] + DFN|INDEX]
REACH|INDEX] + true
2. [Perform DFS on each connected node]
LINK + LISPTR|INDEX]
Repeat step 3 while LINK af NULL
3. [If node has not been reached, continue DFS]
if -REACH[DEST(LINK)}
then PARENT|DESTIN(LINK)] — INDEX
Call LOW_COMPUTE(DESTIN(LINK))
LOW[INDEX] + MIN(LOW{INDEX],LOW|DESTIN(LINK)])
If LOW|DESTIN(LINK)] > DFN[INDEX]
then CUTVERT|INDEX] + true
else If DFN[DESTIN(LINK)] <<DFN[INDEX] and PARENT{INDEX]
DESTIN(LINK) and DFN[DESTIN(LINK)] <LOW{INDE}
then LOW[INDEX] <— DFN[DESTIN(LINK)]
4. [Finished]
Return
S00
EXERCISES SECTION 5-4.6 PAGE 458
5-90
3. [If node has not been reached, make recursive call]
If -REACH|DESTIN(LINK)]
then FLAG(LINK) + true
Call DFS_SPAN(DESTIN(LINk))
LINK + EDGEPTR(LINK)
4. [Finished]
Return
5-91
1. [The tree will have N — 1 edges]
Repeat thru step 6 for] = 1, 2, ...N
2. [Initialize indices]
LOW_I+ LOW_J+0 |
LOW_VALUE < oo
3. [Scan through matrix rows]
Repeat thru step 5 fori = 1, 2,... N
4. [Scan through matrix columns]
Repeat thru step 5 for j = 1, 2, ...N
5. [Is this edge less expensive?|
If Ali,j] > 0 and Afi,j] < LOW_VALUE
then LOW_VALUE + Aji,j]
LOW_I +i
LOW.I <j
6. [Insert this edge into the tree]
A[LOW_I,LOW_J] + A[LOW_J,LOW_I] — -A[LOW_LLOW_J]
7. [Finished]
Return
HD
We
WD
= oooocco 888888
So:
Oo
O'S
NO_EDGES = 0
NO_NODES = 0
ORIGIN = 1
INFO = vl
WEIGHT = 3
END = 2
o792
NO_NODES, NO_NODES is incremented by 1. POINTER[NO_NODES] is
set to NO_NODES + 1, NO_EDGES is incremented by 1, TIME[NO_EDGES]
is set to WEIGHT, and DEST[NO_EDGES] is set to END. Step 5 then reads
in ORIGIN, INFO, WEIGHT, and END.
NO_EDGES =
NO_NODES = 1
ORIGIN = 1
INFO ="!
WEIGHii—s2
END ==3
NO_EDGES = 2
NO_NODES = 1
ORIGIN = 2
INFO = v2
WEIGHT = 2
ENDi= 4
35>95
NODE NO. | DATA TE TL POINTER | TIME DEST
1 vl 0 co 1 3 a
Oy v2 0 co 3 oy, 3
3 A 0 oO 0 2 4
4 ae 0 oo 0
5 g 0 0 0
6 4 0 oO 0
NO_EDGES = 3
NO_NODES = 2
ORIGIN = 2
INO = '!
WEIGHT = 3
END =—5
NO_EDGES = 4
NO_NODES = 2
ORIGIN = 3
INFO = v3
WEIGHT = 4
END = 4
NO_EDGES = 4
NO_NODES = 2
ORIGIN = 3
INFO = v3
WEIGHT = 4
END = 4
NO_EDGES = 6
NO_NODES = 3
ORIGIN = 4
INFO = v4
WEIGHT = 2
END = 6
ante
NODE NO. | DATA TE TL POINTER | TIME DEST
1 vl 0 oO 1 3 2
2 v2 0 oo 2 3
3 v3 0 fore) 5 2 4
4 v4 0 co a os 5
5 dk 0 oo 0 4 4
6 i 0 oO 0 3 6
2 6
NO_EDGES = 7
NO_NODES = 4
ORIGIN = 5
INFO = v5 _
WEIGHT = 1
END = 6
NO_EDGES = 8
NO_NODES = 5
ORIGIN = 6
INFO = v6
WEIGHT = 0
END = 0
5=96
NODE NO. | DATA ©TE°> TL ROINTER | TIME. DES?
1 vl 0 oo 1 3 2
2 v2 0 CO 3 i, 3
3 v3 0 co 5 2 4
4 v4 0 oO 7 3 5
5 vo 0 co 8 4 4
6 v6 0 oO 9 5 6
2 6
1 6
NO_EDGES = 8
NO_NODES = 6
ORIGIN = 6
INFO = v6
WEIGHT = 0
END = 0
Sat
6
3
5
5
2
4
2
4
3
4
2
1
0
1
0
0
0 .
5 Wey lvl
ay
3 3 v3
4 4v4
5
6 6 v4
NODE NO. TE TL
1 0 0
2 3 4
3 2 2
4 6 6
5 6 i
6 8 8
1. [Initializations]
Read( WEIGHT,ORIGIN,END)
P < NNODE
TEMP + P
DATA(P) + ORIGIN
TE(P) + 0
TL(P) + 00
5-98
IN(P) + OUT(P) + LINK(P) + NULL
NO_NODES +- 1
END_FLAG +¢- false
Ze [Process remaining data]
Repeat thru step 9 while ~END_FLAG
3. [Check for error on input]
If ORIGIN > NO_NODES
then Write(/DATA OUT OF SEQUENCE’)
Exit
If ORIGIN = NO_NODES and END < 0
then Write(/NONSINK NODE HAS AN EDGE WITH INVALID
DESTINATION’)
Exit
4. [New originating node?]
If ORIGIN > NO_NODES
then If LINK(TEMP) 4 NULL
then TEMP + LINK(TEMP)
If DATA(TEMP) 54 ORIGIN
then Write(/BAD SOURCE OR SINK’)
Exit
NO_NODES «+ NO_NODES + 1
If END < 0
then Exit
5. [Is END node in the list?]
SAVE «+ TEMP
X + LINK(TEMP)
FOUND ~< false
Repeat while X 54 NULL and ~FOUND
If DATA(X) < END
then FOUND < true
else SAVE + X
X + LINK(X)
If X = NULL
then Y <= NNODE
DATA(Y) + END
TE(Y) + 0
TL(Y) — oo
IN(Y) + OUT(Y) — NULL
LINK(SAVE) — Y
LINK(Y) + X
NEY,
else If DATA(X) +4 END
then Y <= NNODE
DATA(Y) + END
TE(Y) + 0
ara
TL(Y) + o0
IN(Y) + OUT(Y) — NULL
LINK(SAVE) + Y
LINK(Y) — X
x ey:
6. [Set up edge node]
Y +«- ENODE
OUTL(Y) + INL(Y) — NULL
SOURCE(Y) + TEMP
TIME(Y) + WEIGHT
DEST(Y) + X
7. [Insert edge into OUT list of TEMP]
If OUT(TEMP) 4 NULL
then SAVE «+ OUT(TEMP)
Repeat while OUTL(SAVE) +4 NULL
SAVE + OUTL(SAVE)
OUTL(SAVE) + Y
else OUT(TEMP) — Y
8. [Insert edge into IN list of X]
If IN(X) 54 NULL
then SAVE + IN(X)
Repeat while INL(SAVE) 54 NULL
SAVE + INL(SAVE)
INL(SAVE) — Y
else IN(X)+ Y
9. [Get next edge]
If there remains input data
then Read(WEIGHT,ORIGIN,END)
else END_FLAG + true
10. [Finished]
Exit
5-100
Repeat while EDGE# 4 NULL
TEMP « DEST(EDGE#)
TE(TEMP) + MAX(TE(TEMP),TE(NODE#)+TIME(EDGE#))
EDGE# «+ OUTL(EDGE#)
TOP + TOP +1
S[TOP] + NODE#
NODE# «+ LINK(NODE#)
EDGE# + OUT(NODE#)
3. [Initialize to compute TL values]
TL(NODE#) + TE(NODE¥#)
4. [Compute TL values for each node]
Repeat while TOP > 1
NODE# + S[TOP]
TOP — TOP - 1
EDGE# + OUT(NODE#)
Repeat while EDGE# +4 NULL
TEMP «+ DEST(EDGE#)
TL(NODE#) — MIN(TL(NODE#),TL(TEMP) — TIME(EDGE#))
EDGE# + OUTL(EDGE#
5. [Output the nodes on the critical path]
Repeat while NODE# + NULL
If TE(NODE#) = TL(NODE#)
then Write(DATA(NODE#))
NODE# + LINK(NODE#)
6. [Finished]
Exit
The storage required to represent the PERT graphs is directly related to the
number of edges and nodes in the graph. Obviously, the array representation
is much more efficient than the linked representation when considering storage
use.
Execution time required for small PERT graphs does not differ
significantly between the two representations. For larger graphs, the array
representation takes a significantly longer time to execute than the linked
represenation. This may not be the case for extremely large graphs since the
linked method requires chaining through linked lists to find certain elements
and the array method does not require any searching.
prograrn pert(input,output);
{ This program will form the array structures for a pert diagram as in the
algorithm CREATE. After this is done, the TE and TL values are computed
as in algorithm PROCESS. The nodes on the critical path are then printed
out. }
b=.
const n = 10;
e = 15;
procedure aprocess,
{ This procedure will compute the TE and TL values for all nodes in the
graph and then print the critical path. }
begin
{ initialize to compute TE values }
nodenum := 1;
edgenum := 1;
{ compute TE value for each node }
while nodenum < nonodes do
begin
while edgenum < pointer[nodenum + 1] do
begin
if te[dest[edgenum]| < te{nodenum] + time[edgenum]
then te[dest{edgenum]] := te[nodenum] + time[edgenum];
edgenum := edgenum + 1
end;
nodenum := nodenum + 1
end;
{ initialize to compute TL values }
t![nodenurn] := te[nodenum];
nodenum := nonodes — 1;
edgenurn := noedges;
{ compute TL value for each node }
while nodenaum >= 1 do
begin
while edgenum >= pointer[nodenum] do
begin
if tl[nodenum] > tl[dest/edgenum]] - time[edgenum]
5-102
then tl[nodenum] := tl[dest[edgenum]] — time[edgenum];
edgenum := edgenum - 1
end;
nodenum := nodenum - 1
end;
{ print nodes on the critical path }
writeln; writeln;
writeln('CRITICAL PATH’);
writeln;
writeln(' NODE# DATA’ :17);
for nodenum := 1 to nonodes do
if te[nodenum] = tl[nodenum]
then writeln(nodenum:5,data{ncodenum]:12);
end;
begin
{ initializations }
nonodes := 0;
noedges := 0;
for i:= 1 tondo
te[i] := 0;
for i:=
1 ton do
tllij-:-== 32767;
endflg := false;
{ read data until end of input }
while (not cof) and (not endflg) do
begin
readIn(Origin,
Info, Weight,End);
if Origin < nonodes
then begin
writeln(/DATA OUT OF SEQUENCE’);
errorflg := true;
endflg := true
end
else begin
if Info <> /?!
then data[Origin] := Info;
{ check for new originating node }
if Origin > nonodes
then begin
nonodes := nonodes + 1;
pointer[nonodes] := noedges + 1;
{ check for sink node }
2-103
if End <= 0
then endflg := true
else begin
noedges :== noedges + 1;
time[noedges] := Weight;
dest[noedges] :== End
end
end
else { same originating node as before }
i? End <= 0
then begin
writeln(/ NONSINK NODE HAS EDGE WITH
INVALID DESTINATION’);
errorflg := true;
endfig := true
end
else begin
noedges := noedges + 1;
time[noedges] := Weight;
dest[noedges] := End
end
end
end;
{ print critical path if no errors encountered }
if (not errorfig)
then aprocess
end.
5-104
CRITICAL PATH
NODE# DATA
1 a
3 c
4 d
6 f
prograrn Ipert(input,output);
{ This program will set up the linked structures that reflect the relationships
existing in a pert graph as discussed at the end of section 5-5.1. After this is
done, the TE and TL values are computed for each node and the critical path
is printed out. }
var temp,p,save,y,x:nptr;
Weight, Origin ,End:integer;
nonodes:integer;
esave,z:eptr;
errorflg,endfig,
found: boolean;
SOS
procedure Iprocess;
{ This procedure computes and stores te TE and TL values for each node and
then prints those nodes which lie on the critical path. Note that a stack is
used to go back up the list of event nodes. }
var top:integer;
nodenum,temp:nptr;
edgenum:eptr;
s:array|1..max]| of nptr;
begin
{ initializations }
nodenum := p;
edgenum := nodenumf.out;
top := 0;
{ compute TE values }
while nodenumf.link <> nil dc
begin
while edgenum <> nil do
begin
temp := edgenumf].dest;
if tempt.te < nodenumf].te + edgenumf.time
then tempf{.te := nodenumf.te + edgenumf.time;
edgenum := edgenumf.outl
end;
top := top + 1;
s|top] := nodenum;
nodenum := nodenumf.link;
edgenum := nodenumf.out
end;
{ initializations }
nodenumf.tl := nodenumf.te;
{ compute TL values }
while top <> 0do
begin
nodenum := s[top];
top := top - 1;
edgenum := nodenumf.out;
while edgenum <> nildo
begin
temp := edgenumf.dest;
if nodenum}.tl > tempf.ti — edgenumf.time
then nodenumf.t! := tempf.tl — edgenumft.time;
edgenum := edgenumf.outl
end
5-106
end;
{ output nodes on critical path }
writeln; writeln;
writeln('CRITICAL PATH’);
while nodenum <> nil do
begin
if nodenum{.te = nodenumf.tl
then writeln(nodenumf.data);
nodenum := nodenumf.link
end
end;
ABABA BAB EAB ESAS EAE BOAO EEE E OE SASHES HEHE HEE E+ +}
begin
{ initializations }
nonodes := 0;
readIn(Origin, Weight,End);
new(p);
pt.data := Origin;
Di.tec== 0:
p [stl :==-32767;
pft-inp := nil;
pf.out := nil;
pf.link := nil;
temp := p;
endfig := false;
errorflg := false;
{ process remaining data }
while not endflg do
begin
{ error on input? }
if (Origin < nonodes) or ((Origin = nonodes) and (End <= 0))
then begin
writeln(/DATA OUT OF SEQUENCE OR INVALID
DESTINATION’);
errorfig := true;
endflg := true
end
else begin
{ new originating node? }
if Origin > nonodes
then begin
if tempf.link <> nil
then temp := tempf.link;
2-107
if (temp{.data <> Origin)
then begin
. writeln(/EXTRA SOURCE OR SINK
NODE ENCOUNTERED’);
errorflg := true;
endfig := true
end
else begin
nonodes := nonodes + 1;
if End <=0
then endflg := true
end
end;
if not endflg
then begin
{ is end node in the list? }
save := temp;
x := tempf.link;
found := false;
while (x <> nil) and (not found) do
begin
if xt.data = End
then found := true
else begin
save := x;
x := xf.link
end
end;
if x = nil
then begin
new(y);
y{.data := End;
yt.te := 0;
yt.tl := 32767;
yf.out := nil;
yf.inp := nil;
savef.link := y;
yf.link := x;
xi=y
end
else if xf.data <> End
then begin
new(y);
y{.data := End;
yf.te := 0;
5-108
yf{.tl := 32767;
yt.out := nil;
yft.inp := nil;
savef.link := y;
yf-link := x;
X i= y
end;
{ set up edge node }
new(z);
zt.outl := nil;
zf.inl := nil;
z{.source := temp;
z{.time := Weight;.
z{.dest := x;
{ insert edge into out list of temp }
if tempf.out <> nil
then begin
esave := tempf.out;
while esavef.out! <> nil do
esave := esavef.outl;
esavef.outl := z
end
else tempt.out := z;
{ insert edge into list of x }
if xt.inp <> nil
then begin
esave := xf.inp;
while esavef.inl <> nil do
esave := esavef.ial;
esavef.inl] := z
end
else xf.inp := 2;
{ get next input }
if cof
then endflg := true
else readIn(Origin, Weight,End)
end
end
end;
{ Print out critical path if no errors encountered }
if not errorfig
then Iprocess
end.
9-109
THE FOLLOWING DATA CORRESPONDING TO FIGURE 5-5.1
GENERATED THE FOLLOWING RESULTS:
1
WLW
HD
WH
OrFnNnwr
Ankh
DH
wWWH LO
W
LP
—&
COoAAD
CRITICAL PATH
1
3
4
6
1. [Initializations]
P + PLINK(HEAD)
2. [Test point against arguments|
Repeat while P ge HEAD
If X(p) == x, and Y(P) = y,
then Call PDELETE(HEAD,P)
Return
else P «+ RLINK(P)
3. [Point not found]
Write(/ERROR: NO POINT MATCH’)
Return
5- ia
EXERCISES SECTION 5-5.3 PAGE 498
K? QUEUE °-Q
4 4
7 4-7
4 ts Z
12 NULL
7 2 5
225 NULL
Z 5 1-6
o-1 6
NULL
5 1 3-6
1-3 6
NULL
prog NULL —
NULL 6 3
6 NULL
6 NULL NULL
wn ave
FILE
TRANSACTION
Trace of CONSTRUCT:
RECORD FIELD
3 5
7
RECORD KEY
5
1
RECORD — FILE
5
8
4
RECORD TRANSACTION
5
5 3
FILE TRANSACTION
8
3
FIELD RECORD
qn
STS
RESULTING STRUCTURE:
Trace of DETECT_CYCLE:
IP J. K PRINT
lee NLD
2
3. NULL
4
5, 88 tT
6
Doe tl
8
gu 53
1
5
7
5 0
7 Sie 0
5 7.5 RECORD
7 FIELD
5 RECORD
Structure after execution of step 4:
DESPTR ee
ee lee
Structure after execution of step 5:
la) If we know the address of a block (i.e. the memory location of its first word)
and if we also know the size of the block, then the address of its buddy can be
easily SOtCOR HEL First, observe that the address of a block of size 2! is a
multiple of 2', ie. the address in binary notation has at least i zeros at the
right. Therefore, a block of size, say 32, has an address of the form xx ...
x00000; if it is split, the newly formed buddy blocks have address xx ...
x100000 and xx ... x110000.
In general, then, the address of the buddy of the block of size 2! whose
address is x can be given by:
Det
1. [Determine block size]
IfN>2tm
then Return (NULL)
else I+ 0
Repeat while 2fI<N
I+I+1
2. [Find first available block]
J+1
Repeat while SUC(AVAIL[J]) = AVAIL[J]
Je J+1
IffJ>m
then Return(NULL)
P + SUC(AVAIL{J})
Call DELETE(P)
3. [Split as required until correct size is reached]
Repeat while J > I and J > K
Q.— P +2 f (J - 1)
Call INSERT(Q,J — 1)
J SIZE(P) 2s 1
4. [Allocate block P]
FREE(P) < 1
- Return(P)
5-116
Fo =5
F, =8
F, = 13
F, = 21
F,= 214+5=26
F, = 26+ 8 = 34
F, = 34+ 13 = 47
F, = 47 + 21 = 68
Fz = 68 + 26 = 94
5°
SS
NANG
rm
“ONISSHOOUdMAVIVAAYE
LNIWOOAUALAINOOVLYGdYaLNINOO' “WOO
f 1VYV
as €T TS
eeea
a
“ '"VLVGdAHYaLAdWNOOAYTLAANOO
'§ 1OYV
5-118
“vy EVaGddyaLAdWOOdHULNdIWNOOd
%
1OYV
“ -@<yaLAdWOO
:[T J9dJV
tAyetuy—(¢
a0
ao
nw
“* "@866-LdWNO- “WOO
CY
Sahhg
GAYA LNAINOOANALNAIN OO” “WOO
at -@832-LdWODNISSAOOUdAVLV
9 1OyJV
'* "@8tS-LAdNWOONISSAOOUdAVLVGAHTLNINOOAYALNIWOOVLILVGANALNdIWNOO? “WOO
1g YV
:§ 1EYV
~— “@-LdNG&soo-LdWod
“"
WOO
nnn
mon
on
LoYV
6
“GNGAAHLZ-
'" LdWa8t3-LdWo-
‘WOO
5-920
4a) Algorithm COMPACT_STRING. This algorithm compacts the allocated
strings into one contiguous section at the low-order end of string space. The
allocated string descriptors are assumed to be represented in a vector of
structures, with fields LEN, giving the length of the string, and LOC, giving
the location of the string. NO_ALLOC is a global variable holding the
number of allocated string descriptors.
COMCMPT-228BMPT-2THES$END .
number of storage cells on the availability list has shrunk to size MIN. This
algorithm does not check for such a condition. It is assumed all of the nodes
have the following fields: DPTR, INFO, RPTR, and GARBAGE_MARK: a bit
indicating whether or not the node is accessed by a program variable. M is a
global constant holding the size of one node in memory. MEM_AREA is a
global pointer to the first cell in this area of memory on which the algorithm
is to operate. END_MEM_AREA isa global pointer to the last memory area.
AVAIL is a global pointer to the first cell on the availability list.
VAR_NAME_LIST is a global vector containing J variable names. It is
assumed that all nodes originally have GARBAGE MARK set to false. A
stack S, indexed by TOP, is used in marking the nodes.
5-124
1. [Follow the lists of each variable name, marking nodes}
Repeat thru step 4 forI = 1, 2, ... J
2. [Initializations]
P — VAR_NAME_LISTII] -
GARBAGE_MARK(P) + 1
P — RPTR(P)
TOP+1
SITOP] — NULL
3. [Scan thru variable’s list]
Repeat step 4 while P 54 NULL
4. [Has node been marked?|
If GARBAGE_MARK(P)
then P + S(TOP)
TOP
+ TOP -1
else GARBAGE_MARK(P) + true
If RPTR(P) 54 NULL
then TOP + TOP +1
SITOP] — RPTR(P)
If DPTR(P) 4 NULL
then P + DPTR(P)
else P+ S[TOP]
TOP
— TOP -1
5. [Mark all elements on the availability list]
P + AVAIL
Repeat while (P +4 NULL)
GARBAGE_MARK(P) + true
P + RPTR(P)
6. [Place all non-marked nodes on availability list]
P + MEM_AREA
Repeat while (P < END_MEM_AREA)
If GARBAGE_MARK(P) > true
then RPTR(P) + AVAIL
DPTR{(P) — NULL
AVAIL +P
else (prepare for next invocation)
GARBAGE_MARK(P) + false
P-—P+M
7. [Finished]
Exit
Bate2
6) It is assumed that MIN = 10.
Initially
RequestB
jes |] fe YY
RequestC
[es | [fo
RequestB
par fe
Vi
RequestA
w Ys Ve VY
Release B1
Eau AE
Bs Ae We
RequestA
Release Cl
Request A
Request B
Release A2
SOE DEVE
AE Deye
bes
CHAPTER 6
1. [Initializations]
~' PREVM + HEAD
X + LINK(HEAD)
If X = NULL
then Return
2. {Perform sort] ;
Repeat thru step 5 while LINK(X) 54 NULL
3. [Initialize to find smallest of remaining keys]
MIN + TEMP + X
4. [Find’smallest key]
Repeat while LINK(TEMP) 34 NULL
PREV «+ TEMP
TEMP + LINK(TEMP)
If K(TEMP) < K(MIN)
then
MIN «+ TEMP
PREVMIN + PREV
5. [Readjust pointers]
If X +4 MIN
then LINK(PREVM) + MIN
LINK(PREVMIN) + LINK(MIN)
LINK(MIN) + X
PREVM < MIN
else PREVM +- X
X + LINK(X)
6. [Finished]
Return
L A L
L
t-OI> eee T@>rt
20I>99
T+
L d
|&<s8 |9<7
a
L<9
RAE
o> 9e>
s9>%6
It IT
oe=[I
& >Prl
> 39
a> GE> 9>
89
39>
L|
|
L|anat>
L|ran>@H|d4°
a4
i<e
a0
(1M
so=|s]y
1=(0
11=(JM
(U4
11=(elM
jason] 1S¢ [a4°.L|[ebi> aN
Tl>
t6>
99
9
89>
99>
IT
Gh
Gr
Gh
TI>11 99 bL>
66>39 99
ss>
se=[el1
|
ge==[Tby] T1==[tbi| so=[sb1)
6 8 ZL 9 9 y © @ I or
6 8 Z 9 9 9
|r
mao
LT<Ol
iL
I<e Jb<E£ L<3
ot} Tt
or; 3
£
or; 9
oe
0
31%
¥
¥
L
L
T
Tt
T
0
IT
z
0
oT
oT
ot
gj
z
T
z
T
Uaddn
kIMOT
|
|d-°
(F
Li@i<an
W=dOL|doL
1
|a@7|
gn
6-3
60I> 2-6
8e>21e8
L
6<8
6<0T
18> 6
L8>FL
rZ=([4)4
zs=(2]M
r6>FL
66
¥6>
re=(6)M
L>01
18 bl>
66>
L8>¥6
66=(oT]1
6
ze=(2)1
FL>¥6
¥6=[zbi] 01
is=(z)1|
8
|
L 8 6 bo
OT<OT 6<3
L<L
or 6
L4<OT
2
[OT]
L J.
2
8) L
L/2
6-4
5) Procedure BINARY_TREE_SORT(K,N). This procedure will perform ~
a binary tree sort on a vector K of N records so that the records are ordered
on ascending keys. P points to the newly created tree. It is assumed that
procedures INSERT and INORDER exist: procedure INSERT inserts the given
key into the binary tree with specified root node; procedure RINORDER
traverses the tree in inorder, printing the keys associated with each node.
Given table K:
K[l] 42
K[2] 23
K([3] 74
Ra id
K[5] 65
K[6] 58
K[7} 94
K{[3} 3
K{9] 9
K[10] 87
6-5
ge [tly 6
ae
6-6
zs-igiM
ez-iM | or
M@evL fuoly gw»t xmiKx(ly aan ([chi<l+r agtoL O>tr aL Tost ff ADI GAVS Obici
for}s4
|
(ol
(2ba [s!>
vL a 9>8 8 *
[sia (ola
WB
T1<¢e a L 95h r z
feba
19%
(cla
ag<
iL 952 3S Ir II 1) 'olzb
gg
$3
TI<¢9 a
[thi L
[hy
6-7
FL (tha
lor
3 lela [4b 1 J L>¥hI | #1 L
(slo
It
(cha fi
B
le}ss— L 11<89
(o}i
&& GF
w<s9
9£ac
L>9
leba itl
8
F271)
&
L
TI<L
lela
is—|s41
99<FL
(ty L ge zIr
I
8tt
(ici
&
i1{tIy
L>2%
at,
[t4+24
=a-o
[rha<
45L TOSt ¢ ABM BAYS 1 Oly—-MN
B
Ami<[hi don dio, O>tty
eelely
<<
0o-[M
L 9E< SF cE
all
or<89
a0
ss]
i als ge<gg es
fhi-t oa oL Ami<ithi aton [thi<t4ry dL O>ttr Ato. folu-ftiIN ©
I
co>e
se e 1r—[y
(1M ld [UM
iG
a
It<9e €6<
11
9e<
ez
L a
re e>e
LZ d kL a
|e
Calaere|F CacEe
abe |.)
Se UT
Ir e Tet
I} z ||
{thwlth esti dette
| ge—lehi £2
(21M
capes
se
a +
gees
bi<lG+bi
f¢
lOM-aN
xai<ib
fbi
Lost
IaL
GAVS
©ABM
4-2
a-n
O>tr
aon |e eles
6-9
HEAP_SORT creates a heap:
K{1] 99
K[2] 94
Kal. 74
K[4] 65
5.82
K[6] 42
K(7] 58
Ks} ie ad
K[9]} 36
K[10] 23
Klip. “1
Klas 23
K[3] 36
K[4] 42
K[5] 58
K{[6] 65
Kz) hive
Kis] 87
K{[9] 94
K[10] 99
Procedure ADVANTAGE_MERGE(K,N). Given a vector K, with N
elements, this procedure performs a merge sort on the table, taking advantage
of the order already existing within the table. Ordered sections of the table
are found and the procedure SIMPLE_MERGE is used to merge the sections.
Variables I and J mark the end of the first and second ordered sections
respectively.
1. [Initializations]
I~ 1
2. [Find the first ordered segment]
Repeat while I << N
If K[I] < K[I + ]]
then I[+I+1
else Exitloop
3. [Initial table ordered?|
Ir l= N
then Return
4. [Initialize J]
Scrlel
5. [Find end of second segment and merge|
Repeat while J < N
If K[J] > K[J + 1]
then Call SIMPLE_MERGE(K,],J)
I+ J
a
6. [Final merge]
I,J)
Call SIMPLE_MERGE(K
7. [Finished]
Return
1. [Initializations]
P+Q+1
R+I+1 be
Repeat while P <ITandR< J >
If K[P] < K[R]
then C[Q] — K[P]
P+P+1
else C[{Q] + K[R]
R+-R+1
Q+Q+1
2. [Copy remaining records]
We
then Repeat forS =R,R+1.,..., J
Cla] — Kis
QQ
else Repeat for S =P, P + 1.,..., I
1. [Initializations]
If, A = NULL
then Return(B)
If B = NULL
then Return(A)
If K(A) < K(B)
thenC-—Q+aA
A+B
else C+Q+bB
2. [Compare records and append the smallest]
Repeat while LINK(Q) 4 NULL —
If K(LINK(Q)) < K(A)
then Q + LINK(Q)
else B << LINK(Q)
Q + LINK(Q) + A
A+B
3. [Append remaining unprocessed records]
LINK(Q) + A
Return(C)
1. [Perform sort]
Repeat thru step 4 for J = 1, 2, ...,M
2. [Initialize pass]
Repeat for I = 0, 1, ..., 9
T[I] — B[}] — NULL
R + FIRST
3. [Distribute each record in the appropriate pocket]
Repeat while R 54 NULL
D+ by (obtain the Jth digit of the key K{R))
NEXT +- LINK(R)
If T[D] = NULL
then T{D] + BID] —R
LINK(R) «+ R
else LINK(T{[D]) —R
T[D] +R
LINK(R) + B[D]
R + NEXT
6-12
4. [Combine the pockets]
P+0O
Repeat while B[P] == NULL
P-—P+1
FIRST + PIP]
Repeat fort =P 15P 4+)245,9
PREV < T[I - 1]
If T[l] #4 NULL
then LINK(PREV) < Bil]
else T{I] + PREV
LINK(T{9}) — NULL
5. [Finished]
Return
1) HEAD
co
7
x
loos 6
Insert 6:
pean]
/e]8 [paral/
Insert 7:
Insert 8:
After
Balancing:
Insert 12:
Insert 15:
After
Balancing:
Insert 17:
After
Balancing:
Hex]
=P
appara
AUBExZIN /pskppatal
/19[2[oatal/ /[e[B]patal)
6-15
Insert 9:
ep
CBee
Insert 10:
After
Balancing:
3) Function BAL_DEL(HEAD,X,PATH,LEVEL,DIRECTION). This is
a recursive procedure which deletes the node with information field X from the
height balanced binary tree pointed to by HEAD. A path of the ancestors of
the node is built up using PATH: a vector of pointers to the path nodes;
DIRECTION: a vector specifying the direction taken at each level; and
LEVEL: an index into the vectors at the current level. This function returns a
pointer to the new balanced tree. Procedure REBAL, given below, is invoked
to carry out the rebalancing if necessary.
PATH,LEVEL,DIRECTION) -
(reset links)
BI(PRED) + BI(HEAD)
LPTR(PRED) + LPTR(HEAD)
6-17
RPTR(PRED} + RPTR(HEAD)
Return(PRED)
else (find inorder succ)
SUCC «+ RPTR(HEAD)
Repeat while (LPTR(SUCC) 4 NULL)
SUCC + LPTR(SUCC)
(delete succ)
LEVEL «+ LEVEL + 1
PATH/LEVEL] + HEAD
DIRECTION[LEVEL] < 'R!
RPTR(HEAD) «+ BAL_DEL(RPTR(HEAD),DATA(SUCC),
PATH,LEVEL,DIRECTION)
(reset links)
BI(SUCC) «- BI(HEAD)
LPTR(SUCC) + LPTR(HEAD)
RPTR(SUCC) + RPTR(HEAD)
Return(SUCC)
else (determine what subtree - if any is not empty)
If LPTR(HEAD) +4 NULL
then REPLACE « LPTR(HEAD)
else REPLACE + RPTR(HEAD)
{rebalance thru path)
Repeat for I = 1, 2, .... LEVEL
PARENT +- PATH]
If DIRECTION[]] = ‘L!
then CHILD ~— LPTR(PARENT)
else CHILD + RPTR(PARENT)
If CHILD = HEAD
then If DIRECTION|I] = BI(PARENT)
then BI(PARENT) <- 'B!
else GRANPAR + PATH|I - }]
Call REBAL(PARENT,GRANPAR,DIRECTIONI]})
else If BI(CHILD) <> 'B!
then If BI(PARENT) = 'B!
then If DIRECTION|I] = ‘LU!
then BI(PARENT) < ‘R!
else BI(PARENT) + 'L!
else If DIRECTION|I] = BI(PARENT)
then BI(PARENT) < ‘B’
elee GRANPAR + PATHII - 1]
Call REBAL(PARENT,GRANPAR,
DIRECTIONII])
else If BI(PARENT) = DIRECTION|]]
then BI(PARENT) + ‘B’
else GRANPAR + PATHII - ]]
6=18
Call REBAL(PARENT,GRANPAR,
DIRECTION|]])
Return(REPLACE)
6-20
If MPTR(T) = NULL
then Return(true)
else MDATA(T) — DATA(MPTR(T))
Return(false)
else Write(/NODE DOES NOT EXIST’)
Return(false)
If KEY < MDATA(T)
then (delete middle child)
If DATA(MPTR(T)) = KEY
then MPTR(T) — RPTR(T)
RPTR(T) — NULL
If MPTR(T) = NULL
then Return(true)
else MDATA(T) + DATA(MPTR(T))
Return(false)
else Write(/NODE DOES NOT EXIST’)
Return(false)
If RPTR(T) 54 NULL and DATA(RPTR(T)) = KEY
then (delete right child)
RPTR(T) — NULL
TEMP + MDATA(T)
(reset data indicators of ancestors)
Repeat while Q oa 3h
If X < LDATA(Q)
then If X = LDATA(Q)
then LDATA(Q) — TEMP
Q + LPTR(Q)
else IfX < MDATA(Q)
then If X = MDATA(Q)
then MDATA(Q) — TEMP
Q + MPTR(Q)
else Q «+ RPTR(Q)
Return(false)
else Write(/NODE DOES NOT EXIST’)
Return(false)
2. [Recursive call to delete node]
If X < LDATA(T)
then ONLYONE + 2_3 DELETE(LPTR(T),KEY))
else If X < MDATA(T)
then ONLYONE + 2.3 DELETE(MPTR(T),KEY)
else If RPTR(T) 4 NULL
then ONLYONE + 2_3_DELETE(RPTR(T),KEY)
else Write(NODE DOES NOT EXIST’)
6-21
3. [Fix children of node if necessary]
If ONLYONE
then (left subtree unbalanced?)
If KEY < LDATA(T)
then A + LPTR(T)
B + MPTR(T)
(move left child of middle sibling if possible)
If RPTR(B) 4 NULL
then MPTR(A) — LPTR(B)
LPTR(B) — MPTR(B)
MPTR(B) — RPTR(B)
RPTR(B) — NULL
MDATA(A) + LDATA(B)
LDATA(T) + LDATA(B)
MDTA(B) — MDATA(T)
Return(false)
else (move single node into middle sibling subtree)
RPTR(B) + MPTR(B)
MPTR(B) — LPTR(T)
LPTR(B) — LPTR(A)
LPTR(T) — MPTR(T)
MPTR(T) — RPTR(T)
RPTR(T) + NULL
LDATA(T) + MDATA(B)
MDATA(B) — LDATA(B)
LDATA(B) + LDATA(A)
If MPTR(T) = NULL
then Return(true)
else MDATA(T) + MAXVAL(MPTR(T))
Return(false)
(middle subtree unbalanced?)
If KEY < MDATA(T)
then A + MPTR(T)
B + LPTR(T)
(move right child of left sibling if possible)
If RPTR(B) +4 NULL
then MPTR(A) — LPTR(A)
LPTR(A) — RPTR(B)
RPTR(B) + NULL
MDATA(A) + LDATA(A)
MDATA(T) + LDATA(A)
LDATA(A) — LDATA(T)
LDATA(T) + MDATA(B)
Return(false)
6-22
else (move left child of right sibling ifpossible)
C + RPTR(T)
If C 4 NULL and RPTR(C) NULL
then. MPTR(A) — LPTR(C)
LPTR(C) — MPTR(C)
MPTR(C) — RPTR(C)
RPTR(C) —'NULL
MDATA(A) — LDATA(C)
MDATA(T) + LDATA(C)
LDATA(C) + MDATA(C)
MDATA(C) — MAXVAL(MPTR(C))
Return(false)
else (move single node into left sibling tree)
RPTR(B) — LPTR(A)
LDATA(T) — LDATA(A)
MPTR(T) «- RPTR(T)
RPTR(T) + NULL
If MPTR(T) = NULL
then Return(true)
else MDATA(T) + MDATA(C)
Return(false)
(right subtree unbalanced)
A + RPTR(T)
B + MPTR(T)
{move right child of middle sibling if possible)
If RPTR(T) 4 NULL
then MPTR(A) — LPTR(A)
LPTR(A) — RPTR(B)
RPTR(B) — NULL
MDATA(T) — MDATA(B)
MDATA(A) — LDATA(A)
LDATA(A) + MAXVAL(LPTR(A))
Return(false)
else (move single node into middle sibling subtree)
RPTR(B) + LPTR(A)
MDATA(T) + LDATA(A)
RPTR(T) — NULL
Return(false)
(eZ IZ0Id
We ‘(qndqno4ndut)seaij201q30M}
} styl WIeIZOId
st poUsIsep
04 4UaUIE;dUT
YIOq aq} yLasUlpue ojofop SUIYIIOS[S
1oJ E-Z *sa0I} eyeq
sI peal03 UNIOJI0d
YI0q sUOIzJesUI
pue ‘suolajap
pue 24}
voy st payepdn “A[Zurplooze
FY 243 ‘puse& UoONogiiaa
JO SSoU}991I09
SUI}SISUOD
Jo ue yndyno
Jo 94) 013st ‘Waal
{ .
adé4 4y4dopou
= ‘apou|
Ajapoa
od = ‘(yeajuou‘yeal)
opou= piooved
aseo Ajapou:3e}
od go
:Jeo] ‘(1a8aqut:eqep)
:Jeojuou UL-e4ep])
18a}
‘1ydapou:4d]
pw UL2}e 1930}
-I3dapou:14du
6-24
(43dapou:3yda
‘pue
suonesodo
= ‘(aj2[ep41asa1)
Iva -Jjdapou:ptoy
MouAoy -Ja3aqul:
pueww0d SuoI4eiado:
UOTZOUNY ‘1a30}uI:(13dapou:3)feaxeul
{
‘TL =< y4B10Y & GARY 07 puNo] Jl a1} UIAIS 9} Jl POYOAU! SI [apjeqol Uorjouny
‘QINjonIys a1} paoueyeq & Buluteyureul ‘opou ay} sazojap einpaosoid siyy
‘paqajap aq 0} apou e& Jo Aay ony ‘ay pue aay E-Z & 0} JojUIOd & “4 UaAlH }
((1a8aqut: Aoy‘sydapou:7 1ea)azajapreq aainpasoid
6-25
GBR UBER IEEE OTE E EEE UG GEE ES ISUO EE bE obota tacks as }
:pua
eyep |b =: [eaxeul
{ 4[nsaz uingai }
‘aydur' |b ==: b asta
dr jb =: b uay4
ja <> dr |b Jy
op jeojuou = 3ey |b ayy
{ enjea unurrxeur Joy youvas }
ie" b
{ suoijeziyerqrur }
ujzeq
‘1ydapou:b va
au0 {a014qns
asyey
JI 3 [IVS Sey OM}10 9214} “se01}qQns
peay
st pouunsse
07 oq ©
yeqos afqeiea Surutod07 ayy 4001JO ay} “ainjonsys UOMouNy [EAXVUT
St
payoautl
0} BUIWIa}a
aq} p WNUNXeU
onfea
I punoy
UI 94} WoAIZ -9019qns
{
Ia -1ydapou:b‘o‘q‘e
-Ues[ooq:auo0AJUO9NsaI
dura} :Jasozut:
ulzaq
} are ay} uaIpyIyo
Jo4 {Saaea]
{
H ydt|4
| 3e7 = jea]
uay? ujZeq
} r2[ap932] éPIEq9
{
Jy Aoy =>ly eqyepy
uayy
} fox {punoj
{
a lydiaeqep'
= Aay
6-26
uay} ujZaq
|4 dy=: a9dur]4
]4 dur
==: 19 49d1°
14d1°}4
==: [ta
9 eyepy=: jy lagdy eqep
Jy sydur}4
= [ra
uayp 4[Nsol
=: oni}
asa ujZeq
eyepur|4
=: jagdur'|4
‘eqep’
4Nsol
=: as[ey
pus
pua
osja ujZeaq
UfoqtIM
ACON,)a1e
HLIM3t8AGM GNTVA
= ‘ay';
, SaOd LON (,LSIXA
‘peoy =: b
=:
dulay
‘eqepul'|y
yasar
szoyeorpul
}
{
=:
‘lu
dry
ujZeq way}
=
Jy
a
Aoy
eqep
jaydr
{ ipunoj fox } uayy
ju <> ndr{y yy
{ pitqo 44312 ajajap ysnur } asze
pua
asjey =: y[Nsod
(,LSIXA LON Sao ,‘404
‘, = ANTVA AGM HLIM ACGON,) 819M
UOT
ujBeq as{a
6-27
pue
pue
asjey =: 9[Nsaz
|
‘eqep' jagdur|4 =: eqgepur'
ujZaq as]a
ani) =: 3]hsel usy
pu = dur|3 gy
la =: ydr]4
‘aydi-}y =: sydur|4
uj3aq wey}
kay = eyep'jayydur
|) yy
{ jpunoy fay } uay4
eyepur|) => Aoy Jy
{ éPItq o[pprur aya]ep } asta
pue
as[ej =: 4[Nsol
-duia} =: vyepur |b uayy
‘dulay
‘,
=
eyepul
eqepp
GNTVA ‘,
‘(,LSIXA
=:
eyepy
=
dur |b =: b
|b = Aoy yy
ANIVA
eyepur |b =>
‘(,LSIXA
= {b
eyepy
‘ydr'
AGM
adj|b =: b
LON
yy Aoy
|b
uayy
|b
HLIM AGM
uey? uyZeq
=:
<> op}
Fy Ahoy =>|b
Sao LON
pua
b
asjaagjey AGON,) HLIM
Aay Jy asya
ag[ey
SaOd
pue
bayyn
‘404
=: ACGON,)uyeq
wey}
uyseq
=: as[ey]
UfOplIAn
faq
4Nse1 4Nsel ‘404
=:
Wop
uyZeq pue WNsol
pue
esja uyZaq
Pua
osja
pua
6-28
'
‘eyepy }q =: erepy|)
‘eyepy [q =: eyepurje
qi =: 4d1r}q
‘ydrjq =: ydur}q
‘ydurjq =: 4d,1q
‘dylq =: yndur le
ujZeq ayy
ja <> ndriq sy
{ aqissod Jt Zul[qis e[pplar Jo Pirq wel eaour
}4 =: q
‘yydur'
‘yd]y = 2
uj3eq ueq4
eyep [9 = > ANH
{ jpeoueyequn aai9qns 4J2| } ueyy
auod[uo Jf
6-29
{ Aressooau Jt apou Jo uerpyiyo dn xg }
‘pua
asey ==: euoduo
‘as[ey ==! ypnsed
(,LSIXA LON SHO ,
‘fox, = ANTWA AWM HLIM AGON,)81evM
U[aztIM
ulZaq as{a
(Aay‘s3dr }4)fappeqaz =: euodjuo uayy
ju <> dr] Jy esys
|4)japreqoi =: auodjuo uayy
(Aoy‘a9dur
eyepul'| => Aoy JT esa
(Aox‘19d] |9)japreqor =: euodjuo usy
=>
eyepp
A1H
ly
{ apou azajop 0} []@o aatsinoad }
uj3aq
asja
{ ‘(ajdur
2013
Suyqis |4)peaxeur
prut
‘eqepur as[zj
‘eyepur}q ‘eqepy =:
07 ‘eyepur
‘eqepy end}
14dur{q
apou 13d, -4ydr°
49dur'}4 =:
e7epur'|4
19d]
|y |q fa 4[NsaI
{
ase] je =: gpeoueysqun
=: =: aZuis }q le [tu [4
-aydur
4 =: =
=: =:
aydi-}9
Aydp']4
=: =: 4[Nsel
eyepur|q
eyept =: =: ==: =: dur ujZaq
==: ejyepur|q
aaou dur
ydr}q dur ezepyeyepy
ynsar dy dp
ndr pte
}4 usq? eqepur|y
| esje
== {4
q fq Iq |} ]4 4 {4 lq x
} 0a44qn3
puaujBaq
=
=
6-30
‘ndy je =: ydr|q
{ 4J9] 0} apou aaou }
ujZeq as{e
pue
anjcj ==! 4[Nsez
‘(ajdur9) feaxeul =: evyepur']o
‘eyepur jo =: eyepy fo
‘eqepy Jo =: eqepur}4
feqepy [o =: eqepur fe
qa ==: ydrjo
‘yydrjo =: ydurjo
f‘yydurjo =: dp fo
Jo =: dure
‘aqdp'
6-31
ujZeq ueqy
¢
iu <> dijo Fy ueyy
ju <> oF
{ @Zurqis 34311 Jo pjryo ye] eaour } see
pue
as[ej ==: 4jNsel
‘eqyepur|q =: eyepy{3
‘eqepy [9 =: eyepy le
|}
‘eqepy je =: eyepur
‘eqepy je ==: eyepurle
‘ra =: ydrfq
‘yydr fq =: 4ydy Je
‘yndpje =: ydur fe
uyseq Tey
a <> ndrlq gy
{ afqissod jr Surqis 9J2] JO pyiq> 34311 aout }
‘eqepul|>
as[ej ‘eqyepur}o
=:
‘eyepy and} eyepur'
==:
13d1°
[ra =: age]
4[NSed =:
je 14 [ta
== | { eqepy
Je] end} ejepur’
==:
ju <> ndrjq gy
}
uUlBaq es{a
ujZaq aamqqns
uyZaq way
pua
asja
yq3t
} 43d2°]4
@ {4
=: q‘aydur
=:
pua
asia
uy3eaq
6-32
ujZeq esa
pua
Upp
(,GqUL ALAN e194
ujZeq
ueyy
Ayduia
yooyo
}3[iu
=
aa13
ulZaq
soy
{
Ges G EEE IGE GEG ISI GOOG GARTER ZG UCE AGE RA EE A}
[epleqas
‘pua
qjnsol
==:
‘pua
pua
6-33
pue
eqepur'|4
ase] =:
4[Nsol
‘eqepy
[tae 19 ae
=:
je
=: je gdp
ydriq
ujSoq
asta
aacu apou0} Zurfqis {
qns e013 }
pua
agjey ==! 4[Nsel
‘eyepur|q =: eyepul' |}
‘equpur |4 =: vyepy le
‘eqepy le =: eyepur' le
‘iu =: ydrfq
‘yydrjq =: dpe
dp je =: ydur fe
} yooyosoy yeay apou
{
137 3e7
= jeg,
usyy
J] ezep'|4
= Aoy
Weqs
[{a\==.
9
asia ujZaq
Ujoqtm
Ua AGON,) HLIM ATM ANTVA
= ‘hex,
, Saod LON (,LSIXG
pus
asta ujZeq
}
{ 7
e2pou
=:
azajap
ayoaut
}
{
‘(404
yooyo
euo
é1J91
Pirqo
Jf
4
YOoqs
07 '9)[opreqar
=:
]9
6-34
Ajuo uayy
worjouny 14d]
pusa
pua
:_pua
aE} oi OOH
a OE S IEE
A OU
B EOI EEO EHUBGece
UOTZoUNY Aay‘14dapou:})z198uYeq
-49dapou:(sa8a3ur:
IBA
‘ied
UL:
00]
“4;nsel‘yoo1
11939}
-1)da
ydur'|ind =: Ino asja
ond} =: puno} usyq4
Jeo] = 3e7'lmydur'Jino Jy asja
dr jind =: md ueyy
jiu <> ydrjino Jy esta
dur Jind =: mo wayyy
eqyepur Jind => Aay Jj esja
dj Jano =: mo uayqy
eqyepp lind => Aay Jy
‘ina =: [doy]s
‘T + doy =: doy
ulBeq
op (punoj 40u) pu (jeajuou = 3e4° Jind) afTy
{ 201) aq} puaosep }
‘asjey ==: punoj
== INO
6-35
: { suoneztyerqrat }
; ujZaq
‘UIJOOg: puno}j
‘1y3depou:ind IBA
{ ‘doy Aq paxapul s ‘yor4s
Jeqo[3 oy} Uo 41 BuIAes ‘ToMIesuI IOJ YQed 10}s99Ue 94} SaUIUIEZep sInped0i1d
siqy ‘Kay ‘q1asut aq 0} Aoy MoU 04} pue ‘2014 E-Z 0} JazUIOd & ‘4 UaAID }
{(493aqut: Aay‘1ydapou:3)q;edpug aanpesoid
EIA III TRACT TRACTOR AAA IORIAAA
‘193041:
‘Ijdapou
Aesze:s
Jo doy
[oor
1]
f
pue
‘pua
res TerreTeer
eee rrr
rr seer etter rerteceter
tote
cet etctt ilo Corre
ulzeq
} ayeoro
e mau Jeajuon Jaqj301q
Joy zed{
6-36
mou ‘(b)
3e4°|b
==: ‘Jeajuou
==:
‘ta
} yds ay} amo uarpyryo uaamyoq
d pueb {
Od eraenhed
|
yda]b
|b Wd] =: Jared -ydur
uayy
ulZeq
|b
jred
‘dr
ydurdr
=: ‘lu
|red =:
fied
Jred
4ady
=: ydur
|red
|b
=: ==:
jared
|b
‘opoumou
‘eqyepur
14d],eyepy
=:
‘(aydur
fied
{red
‘eqepy
eyepur
==:eyepur
|b)jpeaxeur
Jred)jeaxeur
‘(agdur|sed)jeaxeu
(agdy
(4ydui|b)jeaxeur =: eqepur|b
‘(4d
jared ajdr
|b)jeaxeur =: eqyepy fb
|b)peaxeur =: eyepy fb
‘aydrjaed =: ydur |b
=:
‘(lu =: dr lied
‘lu ==:
=:
eqepy
eyepur
=:
yydur'
dsr fied
aed
ied
|b
‘ydurjred
{b
yd
=: Wdur
lied
‘@poumMeu
=: [ia
fied
yd =:eyepur
{b)jeaxeur
‘(ydur
|b
=: eyepy
=: eqepy
‘eyepur
|red
|b Jsed)jeaxeur
(49d
[red
=: |b
‘apoumou
4d]
=: |b
‘opoumeu
43dur
=:
‘pua :pus
usayy
ujBeq u2aq}
ulZeq uayy
u[Zeq
6-37
{
<eyepdn
eyepur
aqdur ‘eyepur
6-38
ujZaq wey?
eyep'|y > Aoy
‘jig =: 4ydi°}yoo1u
‘Jeojuou =: 2ey°]joolN
‘(joo1m}mou
uj[Zeq u3sy3
Jeo, = 30419 J
{ {20419 Jeo] aj3urs e oyut WoI;JSUI WIoJsad }
ulZeq asa
@poumMol =! 4[Nsel UaYyy
=3H
ju
{ 50014 Aydula 09Ut UoJesul WIOJsed }
‘((apoumou)
‘kay ==: ejep’ |apoumou
‘Jea] =: Sez" |apoumou
Mau
6-39
, { apou jeajy sou ayeoso }
‘0 ==: doy
{joes ozterzrur }
ulseq
(o0j‘b‘1ed3)surpeqos
Ga EE GREE OUR IEICE IAGO OU REO I Ca aa sa}
yuouieye3s
pua
aay
AuuInp
asje
{
}
ydrjred3
pua
==:eyepur
uyZeq eqyepur
jied3
lied
=:
ueyy
-b
GOUT
SF?
£5
pua
eyep jiydy Jared =: ejepy fied
‘eyepy aed =: ejzepur' aed
‘@pOUMIU ==; 193d] |red
==:
Jred
‘adj
yydurjae d
=:
:4adurjred
ydr‘jied
worjsasut
ysouryja]
{
}
uey4y
ujZeq
eyep jued > Aay
{ Wap[tyo omy seq yuoied }
ujZeq useq4
=
Ndr
x
lied
[lu
-‘T
=:
do4
doy
==:
sed
‘[doq]s
(Aoy‘g)qyed pug
6-40
&uorjsesut
peiaued
wsojsed
}
{
ulZeq es]e
pua
pua
==:
y0olU
4[nSol
==:
‘Aoy
eyepul’]y oo1u
‘eyep' |y =: vezep y
|yoo1g
=:
‘apoumou
30010
19duI'|
=:
‘9
0010
Iydy']
eyepul’
uyZaq as]?
pua
e3epy
19dur' =: 4[Nnsol
yoolu
yoolu
‘eyep==:
qooiu
I4d]']40010
|4
‘Aoy
9==: |
‘apoumal
=!
y0010
|
=:
uayy90] =! Z
eqepurjied Aay> asyaJy
WaTq300] ==![
eyepy jued Aay> JI
puedxea
@ jeqal vary
{ waipyiyo
os yuored
sey¢ }
ujZsq asja
pus
9 ==: 4Nsel
:pue
pus
=:
Aoy
wayyy
|iojsooue
eyepur
=>
asyja
Jy
Aay
eyepul|ioysaoue
Aoy =: eqepy |ioyseoue uayy
6-41
eqepl |[iojsooue => Aoy
“[ = do} =: do}
‘[doq]s =: 10ysaoue
uj3aq
Oop 0 <> do} ajyaa
fapoumoau =: 413d4°| sed
ysourzyZzs
uoyzstasuy
}
{
ujZ3q es{a
pue
Aoy =: eyepur red
=:
jied
‘apoumou
43dur
=:
dr‘
fied
‘aydur
Jared
{ worjsasut aypprur }
u2q4
ujZeq
(eqepurjred > fax) gy este
KRKEAKARAEKAAAKRERRASARKREL
(\*
‘(g:eye
pur’
|4
ivjngey
x ‘gt,
{
«
* ,S:eveprla‘sr:,
Aq “4 ul &
jyudrjied
eywp
«
peep
Weald
‘(.0]‘apoumeu‘ied)sureqas «
‘f |y‘g:,
9019
==!
00] *
Aoy >
ERE
Jo 94} g-Z
« jeat
,9:887'13'¢:,
asja {9804
RK
AKER
{ =
acjayy
SyUa_QUOD
Uayy
00]
€=! apom
ERAARARE
Bey
ERR
|9‘¢:,
Jo lagdy|o
adXy «*,)ouIM
4hsed
4=: Jeoy «,)UfoIIIM
{
pue Jayutod auruayap
ujZaqyy
syuIIday}
KARR
= ujZeq
uay4
Bey
amnpsoold
ERE
[[nu |a w9y4
asa
pus }
RR EREKR
s0jf<>
yoaqo
‘uorysey
{
418
KE RE
sq]
q[Rsol
ylesuileq
==:
‘_pua Pp
'Pp }
ulZaq ueyy
uyZeq
}
‘pus {1y4dapou:})jyurd
aanpasoid
6-42
‘[ld ==: peoy
{ aary aztyerrur }
ujZaq
EEE
Gee B OBO GEST OIA
O EI TAC IEOEATER ATA ATR ATORE AEA
‘pua
pua
pua
pua
{(xydy (agdr
‘(agdur
01dutd
4);4);
}4),u1d
| |
‘(g:j« ,‘g:eyepur fayds|9
6-43
- ‘g:eqepy jagds'|a‘¢:, * ,)UpozliM asye
(02:»* [a « ,)UjaM u8y9
pa = 3yd1°3 Jy
| ydur |4‘g:eyepy Jagdui | ‘¢:, * ,
‘(g:e3epur
Jagdy}y‘g:eqepy lagdy ]9‘G:, * Joy
‘g:eqepur
ujZeq asja
pua
(a9da° }3)9 0tad
‘(agdur }9)9 utd
‘(19dy |9)y utd
leeway
‘g:eyep fagdr']4‘TT:, Jeo] « ,)UjazIM asta
(02: [a * Ulam Ueqy
jiu = 4di"}4 Jy
*
Jey
,jagdur|9‘TT:,
(g:egep
‘g:eyep fagdy'}a‘TT:, Jez] « 271A
} a8e3ueadoo]07 sseooid
[je eyep
{
styyou Joo OP
ulBaq
peas
ul pueururos)
mou‘ ‘(Aoy
J pUCUIUIOD
== Z10SUI
ueyy peoy=: (Aaymou‘peay)qsosuijeq
asta (Aoymou‘peag)azazapyeq
‘pua
} asi2AeI3 YSno143
991309 AJit9A $s00}901I09
{
UfOPLIM
UfO9IAA
oo}«,) AdALAGON
* VLIVd
* VLIVGT
+ VLVGW
1
+,
(#
UldT
Uldd
ULdN*
6-44
‘pua
(peoq)jutid
-VLVd
2]0p
06
Wosut OL
aos = CI
j4osul 02
q19sul
c
USUI2s TI
q1oSul af
P. 22° I
osu= 0¢
Aasul Of
esa! CZs
4aosul
= 1%
49sSul OOT
* * oot * Fer] *
ae
* * 06 * Fert *
Fe Re:
og * Fert °
$8.
* +
ee
* os * * Feejuou *
Oot Fee] 06
8
Se
* * v1 « Feel
* * It * fe *
« * 3 * | *
Se88 Se
* g * * Jeaquou +
Ir
«It
* jesquou «
bt
*
Feat
oot * FL
* GdALHCON *
ie
VIVON * WIVYGI * YWIVd
£
*
Uldy
ISIXd LON SHOd = ENTIVA ADI HLIM AGON
LSIXH LON SHOd (ONT = GTI LIM SGON
AGI VA
HLIM HOON
AGI VA
‘SLTASAY
LISixd LON SHOG_ Tt = GNI
GaYL ALG
1@-99919P —ay9]ap
6-45
L
OI 9}9/9P
- 9}2]9P
OG a}2[9p
0€ 92/9P
932]?
ol 9)}9]9p
«999[9P Sr
= 6G
-999]9P
Go
29]9P
Q19SuUl
OIL
v
TI JAoSUI
FI Jiosul
0S qiosul
Consider a 2-3 tree of height h. As a maximum, every node can have three
children (with the exception of the leaf nodes). This ternary tree has 3" leaf
nodes. As a minimum, every node can have two children (with the exception
of the leaf nodes). This binary tree has 2" leaf nodes. Therefore we can
conclude that a 2-3 tree of height h must have between 2" and 3? leaf nodes.
6-46
then Call REBAL(SUCC,RPTR(SUCC))
else If WEIGHT(LPTR(SUCC)) > WEIGHT(SUCC)
then Call REBAL(SUCC,LPTR(SUCC))
else If WEIGHT(LPTR(SUCC)) > WEIGHT(SUCC)
then Call REBAL(SUCC,LPTR(SUCC))
Return(SUCC)
else If LPTR(SUCC)
4 NULL
then Return(LPTR(SUCC))
else Return(RPTR(SUCC))
1. [Rebalance]
If LPTR(PAR) = CHILD
then LPTR(PAR) + RPTR(CHILD)
RPTR(CHILD) + PAR
else RPTR(PAR) «+ LPTR(CHILD)
LPTR(CHILD) + PAR
2. [Check for further rebalancing]
If LPTR(PAR) 4 NULL
then If RPTR(PAR) + NULL
then If WEIGHT(LPTR(PAR)) > WEIGHT(RPTR(PAR))
then If WEIGHT(LPTR(PAR) > WEIGHT(PAR)
then Call REBAL(PAR,LPTR(PAR))
else If WEIGHT(RPTR(PAR)) > WEIGHT(PAR)
then Call REBAL(PAR,RPTR(PAR))
else If WEIGHT(LPTR(PAR)) > WEIGHT(PAR)
then Call REBAL(PAR,LPTR(PAR))
else If RPTR(PAR) 44 NULL
thenIf WEIGHT(RPTR(PAR)) > WEIGHT(PAR))
then Call REBAL(PAR,RPTR(PAR))
3. [Assign PAR to point to new tree]
PAR «+ CHILD
Return
6-47
bw Procedure OPTIMIZE_REBAL. This procedure is essentially the same
as that given in the text, with the exception that optimization in rebalancing
is taken advantage of with regards to equal access nodes.
6-48
3) Function CHANGE(INFO,NEW_WEIGHT). This procedure changes a
particular node with information equal to INFO, in a weight balanced binary
tree. The weight of the node is changed to NEW_WEIGHT. Procedures
REBAL_UP and REBAL_DOWN are invoked should rebalancing be found to
be necessary. The function returns true if the operation is successful; false
otherwise.
1. [Rebalance]
If LPTR(PARENT) = CHILD
then LPTR(PARENT) « RPTR(CHILD)
RPTR(CHILD) + PARENT
else RPTR(PARENT) + LPTR(CHILD)
LPTR(CHILD) + PARENT
2. [Further rebalancing necessary?]
If LPTR(PARENT) 34 NULL
then If RPTR(PARENT) 3 NULL
then If WEIGHT(LPTR(PARENT))>WEIGHT(RPTR(PARENT))
then If WEIGHT(LPTR(PARENT))>WEIGHT(PARENT)
then Call REBAL_DOWN(PARENT,LPTR(PARENT))
else If WEIGHT(RPTR(PARENT)) > WEIGHT(PARENT)
then Call REBAL_DOWN(PARENT,RPTR(PARENT))
else If WEIGHT(LPTR(PARENT))> WEIGHT(P ARENT)
then Call REBAL(PARENT,LPTR(PARENT))
else If RPTR(PARENT) 4 NULL
then If WEIGHT(RPTR(PARENT)) > WEIGHT(PARENT)
then Call REBAL_DOWN(PARENT,RPTR(PARENT))
3. [Set PARENT to point to new tree]
PARENT + CHILD
Return
1. [Initializations]
GPAR <— NULL
TOP_FLAG + false
2. [Get grandparent from stack]
If -EMPTY(S)
then GPAR + POP(S,TOP)
else TOP_FLAG + true
6-50
3. {Exchange parent and child]
If LPTR(PARENT) = CHILD
then LPTR(PARENT) ~ RPTR(CHILD)
RPTR(CHILD) + PARENT
else RPTR(PARENT) — LPTR(CHILD)
LPTR(CHILD) — PARENT
4, [Set grandparent link]
If -TOP_FLAG
then If LPTR(GPAR) = PAR
‘then LPTR(GPAR) «+ CHILD
else RPTR(GPAR) «+ CHILD
(further rebalancing necessary?)
If WEIGHT(GPAR) < WEIGHT(CHILD)
then Call(REBAL(CHILD,GPAR))
else HEAD + CHILD
5. [Finished]
Return
1. [Initializations]
COL + 1
LAST_COL + 0
LAST_ROW + 0
2. [Perform search and deletion]
Repeat for K = 1, 2, .... LENGTH(NAME)
ROW + INDEX('BABC...XYZ’,SUB(NAME,K,1))
Repeat while(TRIE[ROW,COL] S '-’)
If TRIE[ROW,COL] = NAME
then (perform deletion)
TRIE[ROW,COL] + '-!
(collapse columns if possible)
If LAST_COL 40
then COUNT + 0
Repeat for P=ind- 3 27
6-51
If TRIE[I,COL] = '-!
then COUNT + COUNT + 1
_ SAVE + TRIE[I,COL]
SAVE_ROW + I
If COUNT i= 1
then TRIE[SAVE_ROW,COL] + !-!
TRIE[LAST_ROW,LAST_COL] + SAVE
Return
If INDEX(' 0123456789! ,SUB(TRIE[ROW,COL],1,1)) = 0
then Write(/NAME NOT FOUND’)
COL — ROW <0
Return
else LAST_ROW + ROW
LAST_COL + COL
COL + TRIE|[ROW,COL]
3. [Missing name]
Write('NAME NOT FOUND’)
ROW «+ COL +606
Return :
1. [Initializations]
COL «+ TRIE
2. [Perform insertion]
Repeat thru step 3 for K = 1, 2, ..., LENGTH(NAME)
ROW + INDEX('PABC...XYZ!,SUB(NAME,K,1))
3. [Entry or link?]
If TAG[ROW|(COL)
then (enter key into empty position)
If ENTRY[ROW|(COL) = !-!
then ENTRY[ROW](COL) + NAME
Return(true)
(check for duplicate entry)
If ENTRY{[ROW](COL) = NAME
then Write(/DUPLICATE ENTRY’)
Return(false)
(current position occupied)
NEW «+ COLUMN_NODE
6=52
Repeat for I= 1, 2, ..., 27
TAGI|I|(NEW) + true
ENTRY[I|(NEW) < !-!
SAVE — ENTRY[ROW](COL)
TAG[ROW](COL) + false
LINK[ROW](COL) ~NEW
ROW + INDEX (‘PABC...XYZ')
TAG[ROW](NEW) + true
ENTRY{ROW](NEW) — SAVE
COL + NEW
else (determine next column)
COL + LINK{[ROW](COL)
1. [Initializations]
COL + TRIE
2. [Perform the search]
Repeat for K = 1, 2, .... LENGTH(NAME)
ROW + INDEX('PABC...XYZ! ,SUB(NAME,K,1))
Repeat while (sTAG[ROW|(COL) AND LINK[ROW|(COL) 34
NULL) or (TAG[ROW](COL) and ENTRY|ROW](COL) 34 “')
If TAGIROW](COL)
then If ENTRY[ROW|(COL) = NAME
then Return
else Write(/UNEXPECTED NAME FOUND’)
ROW <— 0
COL «+ NULL
Return
else COL + LINK[ROW](COL)
3. [Missing name]
Write(’ NAME NOT FOUND‘)
ROW +0
COL + NULL
Return
4) Function LINK_TRIE_DELETE(NAME,TRIE). Given the parameters
as described in question 2 above, this function deletes the entry with key field
NAME from the given trie structure. The function returns true if the deletion
is successful; false otherwise.
1. , [Initializations]
COL + TRIE
LAST_COL + NULL
LAST_ROW + 0
2. [Perform search]
Repeat for K = 1, 2, ..., LENGTH(NAME)
ROW + INDEX('PABC...XYZ',SUB(NAME,K,1))
Repeat while (>TAG[ROW|(COL) and LINK[ROW](COL)
NULL) or (TAG|ROW](COL) and ENTRY|ROW|(COL) Die )
If TAG[ROW](COL)
then If ENTRY[ROW|(COL) = NAME
then ENTRY[ROW|(COL) + '-!
If LAST_COL + NULL
then COUNT + 0
Repeat for I = 1, 2, ..., 27
If TAG[I](COL)
then If ENTRY{I|(COL) 4 '~!
then COUNT + COUNT +1
SAVE_E «— ENTRY[I](COL)
SAVE_T + TAG|I](COL)
SAVE_ROW + I
else COUNT + COUNT + 1
SAVE_L + LINK{I](COL)
SAVE_T — TAG[I](COL)
SAVE_ROW + I
If COUNT = 1
then TAG[SAVE_ROW](COL) + true
ENTRY|[SAVE_ROW]{COL) + !-!
TAG|LAST_ROW](LAST_COL)
+ SAVE_T
If SAVE_T
then ENTRY[LAST_ROW]
(LAST_COL) — SAVE_E
else LINK{[LAST_ROW]
(LAST_COL) + SAVE_L
Return(true)
else Write(/NAME NOT FOUND’)
Return(false)
else LAST_ROW + ROW
LAST_COL + COL
COL + LINK[ROW](COL)
6-54
3. [Missing name]
Write(/ NAME NOT FOUND’)
Return(false)
var t:ptr;
command:operations;
data:string;
i:char;
try :boolean;
tabover:integer;
GABE E EEE SEE AEE EOE EAE EOS S SEES ESA EEG GA EE EE EEE
#include ‘getline.i';
#include 'length.i';
GABE SSE ISAS EAS EEE ES TSE EI EEK EERE EEE EEE EEE EE EE }
var p,q,save:ptr;
k:integer;
row:char;
fini,result:boolean;
6-55
begin
{ initializations }
q:= t;
k= 1:
fini := false;
{ perform insertion }
while (k <= length(key)) and (not fini) do
begin
{ determine next letter }
if (key[k] = ‘|') or (key(k] = ‘ ‘)
then row := '“
else row := key|k];
{ insert key into empty position }
if qf.tag = nonleaf
then if qf.index{row] = nil
then begin
new(p);
pf.tag := leaf;
pf.name := key;
qf.index[row] := p;
result := true;
fini := true
end
else { check for duplicate entry }
if qf.index[row]f.tag = leaf
then begin
if qf.index|row]f.name = key
then begin
writeln;
writeln(/ DUPLICATE KEY: ':15,
key :length(key));
result := false;
fini := true
end
else { current position occupied }
begin
save := qf.index[row];
new(p);
pf.tag := nonleaf;
for i:=' to ‘z' do
pt.index{i] := nil;
qt.index[row] := p;
if (savet.name[k+1] = ‘|') or
(savet.name[k+1] = ‘ ‘)
then row := '“
else row := savef.name[k+1];
pt-index[row] := save;
q:=p
end
end
else q := qf.index/row]
else q := qf.index{row];
k= k +1
end;
trieinsert := result
end;
{ This function deletes the entry with name key from the trie structure given
by t. The function returns true if the deletion is successful; false otherwise. }
var p,q,lastcol,save:ptr;
row, Saverow, lastrow,i:char;
k,count:integer;
fini,result:boolean;
begin
fini := false;
result := false;
q:=t
lastcol := nil;
lastrow := ! !;
k= 1;
{ perform search and deletion }
while (k <= length(key)) and (not fini) do
begin
{ determine next letter }
if (key[k] =‘ ') or (key|k] = ‘|')
then row := !"
else row := key|k];
p := qf.index[row];
while (p <> nil) and (not fini) do
begin
{ name found? }
if p{.tag = leaf
then if pf{.name «= key
then begin
6-57
qf .index[row] := nil;
if lastcol <> nil
then begin
count := 0;
for i:='" to 'z! do
if qt.index|i]<> nil
then begin
count := count + 1;
save := qf{.index{i];
saverow := i
end;
if count = 1
then begin
qf .index|saverow] := nil;
lastcolf .index[lastrow]
‘= save
end
end; ,
result := true;
fini := true
end
else begin
result := false;
fini := true
end
else begin
lastrow := row;
lastcol := q;
q:= Pp;
p := pt.index{row|
end
end;
k:=k+1
end;
{ missing name }
if not result
then begin
writeln;
writeln(/ NAME NOT FOUND = ':17,key:length(key))
end;
triedelete := result
end;
6-58
BABIES EASA aaa EIA Sa Aa AIA
EEO EBDESERIES
LEBER EEE EE
procedure print(t:ptr;tabover:integer);
var i:char;
tabstring:string;
j:integer;
begin
{ check for empty tree }
ift <> nil
then begin
{ print info }
writeln;
for j := 1 to SOD ONY a
tabstring|[j] :=
tabstring|tabover+1] :=
writeln(tabstring: Teeside "'NODE' TYPE = /:12;¢f. tag);
if tf.tag
= leaf
then writeln(tabstring:length(tabstring),/
NAME = ':7,
tt.name:length(tf.name))
else begin
for i:='" to'z' do
begin
if tt.index{i] <> nil
then begin
writeln(tabstring:length(tabstring),
‘INDEX = ':8,i:2);
print(tf.index{i],tabover + 20)
end
end
end
end
end;
(FEBS SEE SEERA ASAE AGA AE EGE EE EEE EEE EEE EE EEE}
begin
{ initializations }
tabover := 1;
new(t);
tt.tag := nonleaf;
for i:='“ to'z' do
tf.index[i] := nil;
6-59
{ process all data }
while not eof do
begin
read{command);
getline(data);
if command = insert
then try := trieinsert(t,data)
else try := triedelete(t,data)
end;
print(t,tabover)
end.
DATA:
delete fred
insert. barney
insert wilma
insert betty
insert bam-bam
insert pebbles
delete bedrock
insert ~ quarry
insert bedrock
insert fred
insert dino
insert flintstone
delete barney
insert fred
insert slate
insert hatrock
insert rubble
delete bedrock
RESULTS:
PAY:
h = x mod 101
= (215 + 193 + 232) mod 101
= 640 mod 101
ya
6-61
RATE:
h = x mod 101
= (217 + 193 + 227 + 197) mod 101
= 834 mod 101
== 26
AGE:
h = x mod 101
= (193 + 199 + 197) mod 101
= 589 mod 101
= 84
NUMBER:
h = x mod 101
= (213 + 228 + 212 + 194 + 197 + 217) mod 101
l 1261 mod 101
49
PAY:
h = x mod 101
= (80 + 65 + 89) mod 101
= 234 mod 101
== 32
RATE:
h = x mod 101
= (82 + 65 + 84 + 69) mod 101
= 300 mod 101
= 98
AGE:
h = x mod 101
= (65 + 71 + 69) mod 101
= 205 mod 101
= 3
NUMBER:
h = x mod 101
= (78 + 85 + 77 + 66 + 69 + 82) mod 101
= 457 mod 101
= $1
6-62
5
Ei
5
:
Table
of
Contents
Record PAY
Inserting
After RATE TAX PENSION STATUS
DEDUCT SEX SALARIED
DEPENDENTS
6-63
Procedure LP_DELETE(X). This procedure deletes the record with given
key X, from the hash table, using the linear probe technique.
1. [Calculate position]
d + HASH(X)
2. [Locate record]
fhe x
then i+d+1
FOUND + false
Repeat while i 54 d and 7FOUND
If kK, =X
then FOUND + true
else I+ I+1
3. [Was record found?]
If ~FOUND
then Write(/RECORD NOT FOUND IN TABLE! )
Return
4. [Delete record]
Kk; — Empty
mark + i
Repeat for} = mark + 1, mark + 2, ..., m— 1, m, 1, ..., mark - 1
If K; 4 Empty
then If HASH(K,) < i
then K,+ k;
ic j
kK, + Empty
5. [Finished]
Return
6-64
CHAPTER 7
FILE STRUCTURES
EXERCISES SECTION 7-1 PAGE 636
and record size refers to the number of bytes per record. The above formulae
can be combined and simplified into a concise form to solve for #records.
dees tape length
oes record size interblock gap
encoding density blocking factor
te — _ (3600ft)(12in
30 08t /ft)
Lip 80 byte 3/4in
1600 byte/in 1
= 54000 records
43200 in
records = —————________—_
ir ; 80 byte 3/4 in
1600 byte/in 5
= 216000 records
43200 in
records = —————_$_$_______—__
i 80 byte 1/2 in
3200 byte/in 25
= 960000 records
43200 in
records = ————_________
# 80 byte 1/2 in
800 byte/in s 1
= 72000 records
effective #bytes
to—
effective tape density =
length of tape
where effective #bytes = length of tape
— xX block size
block size
+ gap size
s. encoding density
therefore effective tape density = lock size
block size
+ gap size
s. encoding density
3a) 1 3/4Betts
in
effective tape density = se05Bpteic 80 byte
= 100 byte/in ;
1 3/4 in |
b) effective tape density = Genes 400 byte
= 400 byte/in
ay
1 3/8 in
effective tape density = Sas 25(80 bytes)
= 2000 byte/in
= 133 byte/in
d si se interblock
eee ere eee
= #records X ( eee
encoding density X rate info blocking factor X rate gap
a) Beet s 80 bytes
OU MAa 3/4 in
time = Z 54000 1600 bytes/in X 125a in/se
s bc it Pec
1 X oma nt:oncc
30 in/se
Tas
= 1372 seconds (22.9 minutes)
80 bytes 3/4 in |
ime. ==) 216000 | ee ee ene
me : |1600 bytes/in X 125 in/sec 5 X 30 in/sec
= 1166 seconds (19.4 minutes)
80 bytes 1/2 in
ti = 960000 | ——_——_——__—____ + — ;
aa 3200 bytes/in X 125 in/sec 25x 30 in/sec
d)
te 72000 | 80 bytes 1/2 in |
800 bytes/in X 125in/sec 30 in/sec
= 1258 seconds (21.0 minutes)
__ 4 168 char/sector
_ 2 records
sector
(sectors/track) = 64 sectors/track
therefore,
sector track
#tracks = {10000 records x
2 records 64 sectors
= 79 tracks
23
TG) sector size
transmission rate
therefore,
Recall that the entire sector of a UNIVAC FASTRAND II drum must be read
(independent of actual space used). The assumption that the sectors are in
random order implies the consideration of the seek and latency times at every
sector address. If, instead, the sectors were sequential, these delays need be
considered only once for each track.
block size: 20 records each 80 bytes long and 14 bytes system information
block size = 1614 bytes
#tracks: 20 records/block
500 blocks for the file
12 blocks/track
#tracks = 42
therefore
7-4
8a) 64 char
i
nae aaa 3000 char/ms
ee
= 24.3213 ms
char
64 AGRE
e
i
time(D EC RM80) = 25 ms + 8.3 ms + Ta
= 35.3528 ms
ceo
time(COMM D9000) = 153ms + 8.3 ms + —
500 char/ms
= 161.428 ms
The time required to update a 64-char record equals the sum of the time
required to read the 64-char record and 2 X T(i), the time of one period of
revolution.
time
time-DEC RM80 = #sectors *
sector
ai +
: + 50)
z [Za iz,
record size |
a # records
sector size | transmission rate
record size
[er
‘1212 chars/ms
== #records * 4.17 ms
time - time
=) S
track Sti) 2 Serene block
time - f
block = LU) + Thi)
f=5
we sector size
Li} —
transmission rate
__ #records
# block
blocks 50
#blocks
#tracks =
#blocks
tracks
#records/20
track size
block size
_ __#records/20 __
20483 char/track
1294 char/block
__ #records
316.6
time-IBM 2391 =
#records
316.6
:
[o+ #records 50* 9.68 ms
Therefore:
#records = 2727.73
Therefore each file should contain 2728 records in order that the total read
time be (approximately) equal.
7-6
EXERCISES SECTION 7-3 PAGE 649
bo— There are 11 mutually exclusive valucs in the range. Using the binary
encoding scheme an item length of [ log. 11] = 4 is required. Now all that is
left is to assign each value in the range a unique binary number of length four,
five more cities can be added to the list before the code length must be
increased.
1. {Initializations]
Repeat for I = 1, 2, ..., N
Til] + P[]j
Hil] gen
L{]] — 0
2. [Set up combining loop]
Repeat thru step 8 for I = 1, 2, ..., N-1
3. [Get index of lowest probability]
LOW1 + LINK + MIN(T)
SAVE < T[LOW]]
T[LOW1] + HIGH_VALUE
4. [Concatenate a zero to the front of each partial code in this group]
Repeat while LINK = 0
H[LINK] ~ ‘0’ © H{LINK]
LINK + L{LINK]
5. [Get index of next lowest probability]
LOW2 + LINK + MIN(T)
6. [Combine probabilities]
T[LOW2] + TILOW2] + SAVE
7. [Concatenate a one to the front of each partial code in this group]
Repeat while LILINK] 4 0
iy
H[LINK] — ‘1! 0 HILINK]
LINK < L/LINK]
H[LINK] — '1' 0 H/LINK]
8. [Extend the group by adding a new link]
L[LINK] — LOW!
9. [Finished]
Return
3. [Nontrivial case?|
IfN 1
then Call R_HUFF(P,N,H)
4. [Finished]
Return
n
Vk xX P;
i=I1
#9
(2 x 1/4) + (3 x 1/6) + (3 x 1/8) + (3 x 1/8) + (3 x 1/12) + (4 x 1/12)
+ (4 X 1/16) + (4 x 1/24) + (5x 1/48) + (6 X 1/48) + (6 X 1/48) = 3.10
bits
nD
Applying this formula to the probabilities (in question 5) of the item values in
question 2, we have:
ye10
8) WORD POSITION(S) WORD POSITION(S)
a 7,98 memory 43,68
accessible 65 not ol
all 52 of 10, 18,67
an 63 on 21
and 19,27 only Dae
applied 31 operations 20
are 45 point 3
assumed 38 portion 9
at 46 processed 56
by 57 reasons 49
computer 59 representations 17,26
data 22,28,34 reside 40,61
dealt 14 should 60
described 30 storage 25
discussion 12 structures 23
entities 35 text 6
form 66 that 54
has 13 the 5,11,16,24
immediately 64 there 44
in 4,41,62 this 2
information 53 to 1,33,39
is 55 two 48
least 47 were ot
main 42 which 36
major 8 why 50
manipulations 29 with 15
la) If search requests are not batched, there is no advantage in ordering the file
assuming almost all requests access existent records. The average search time
is N/2 in either case where N is the number of records in the sequential file.
However (note difference from question 2), if a large proportion of attempted
retrievals involve illegitimate keys then the search time will be N if the file is
Prt)
not ordered, and N/2 if the file is ordered. The frequency of unsuccessful
searches must be weighed against the overhead in ordering the file.
If the search requests are batched then there is an advantage in ordering the
file provided that the search requests are ordered (by the same key) and the
number of requests is high (enough to overcome the overhead in ordering the
file). The saving in total-search time exists because it is not necessary to scan
the file from the beginning each time a request is made. Instead searching
continues from where the previous search left off. The importance of ordering
the search requests should be evident.
Stream I/O
- information is stored externally on a file in character form
- I/O is at item level
- character conversion takes place in buffer
- buffer size is independent of stored information
Consecutive I/O
- information is stored in internal form
- I/O at record level
- no data conversion required
- buffer contains integral number of logical records
Tae,
1. [Initializations]
Open MASTER for input
2. [Process all subordinate index blocks listed in master index block]
X «+ number of subordinate index blocks in master index block
Repeat thru step 5 for I = 1, 2, ..., X
3. [Process all data blocks listed in subordinate index block]
A — ADDRESS of MB_REC|]]
Move block of address A to subordinate block buffer
Y «+ number of data blocks in subordinate block buffer
Repeat thru step 5 for J = 1, 2, ..., Y
4. [Process all records in data block]
A + ADDRESS of SIB_REC{J]
Move block of address A to data block buffer
Z + number of records in data block buffer
Repeat step 5 forK = 1, 2, ..., Z
5. [Process individual record]
A + ADDRESS of DB_REC|K]
Process transactions posted against DB_REC(A)
6. [Finished]
Exit
1. [Initializations|
Open MASTER file for update
Read TRAN_REC
2. [Exarnine master index block]
MB_LOC — BIN_BLOCK_SEARCH(KEY of TRAN
SIB_ADDR «— ADDR ofMB_REC(MB_LOC)
_REC, master block )
Move block at SI_LADDR in MASTER file to subordinate index block
buifer in main memory
3. [Examine subordinate index block]
SIB_LOC + BIN_BLOCK_SEARCH(KEY cf TRAN_REC, subordinate
index block buffer) ©,
Jag
DB_ADDR ~— ADDR of SIB_REC(SIB_LOC)
Move block at DB_ADDR to data block buffer in main memory
4. [Examine data block index]
DBI_LADDR + address of index record in data block buffer
DBI_LLOC + BIN_BLOCK_SEARCH{KEY of TRAN_REC, data block
index of data block buffer)
MTR_ADDR + ADDR of DBI_LREC(DBI_LOC)
5. [Matching keys?]
If KEY of record MTR_ADDR ee KEY of TRAN_REC-
then If TRANS = 'ADD!
then Call SCOPE_INSERT
else Write(/TRANS KEY DOES NOT MATCH A FILE KEY’ )
Exit
6. [Deletion or update?]
If TRANS = 'DELETE!
then Call SCOPE_DELETE
else If TRANS = ‘ALTER!
then Call SCOPE_ALTER
else Write(/‘INVALID TRANSACTION’)
Exit
1. [Initializations]
E + number of records in block
B+-1
BASE_ADDRESS + address of first record in block
REC_SIZE + size of record in block
Repeat thru step 3 while B < E
2. [Obtain address of middle record in unsearched portion]
I+ [{B + E)J
ADDR «+ BASE_ADDRESS + (I - 1) * REC_SIZE
3. [Compare]
If SEARCH_KEY < KEY of record at ADDR
then. 1 — [1
else If SEARCH_KEY > KEY of record at ADDR
then” Bae l
else Return(ADDR)
4. [Return address where record should be]
If KEY of record at ADDR < SEARCH_KEY.
then Return(ADDR + REC_SIZE)
Y
else Return(ADDR)
seal
Procedure SCOPE_INSERT. This procedure creates a new record, and
inserts it at MTR_ADDR in the data block buffer. Since records may have to
be moved, the data block index record should reflect the change. A block
splitting algorithm may be called if the data j:iock buffer is full; it is
responsible for changing index entries in the subordinate index block, and the
master index block if a subordinate index block overflows. Details of the
splitting algorithm will not be given but we can assume that after the call the
proper data block will be in the data block buffer. The local variables are
REC_ADDR, REC_PREV, IND_ADDR, and IND_PREYV, all of which contain
addresses of index entries in main memory.
Pats
1. [Initializations]
REC_ADDR «+ MTR_ADDR
IND_ADDR «+ DBI_LADDR
2. [Move data block buffer records and corresponding index entries|
Repeat while REC_ADDR sa address of last record in data block buffer
REC_SUB < address of record following DB_REC(REC_ADDR)
IND_SUC + address of index entry following DIB_LREC(IND_ADDR)
DB_REC(REC_ADDR) «- DB_REC(REC_SUC)
DBI(IND_ADDR) + DBILREC(IND_SUC)
REC_ADDR «+ REC_SUC
IND_ADDR «— IND_SUC
Delete DB_LREC(REC_ADDR) from data block buffer
3. [Only record of data block buffer released?|
If address of first record in data block buffer = REC_ADDR
then release block at DB_ADDR in MASTER file
REC_ADDR + SIB_LOC
Repeat while REC_ADDR Sa address of last record in SI buffer
REC_SUC + address of record following SIB_REC(REC_ADDR)
SIB_REC(REC_ADDR) + SIB_REC(REC_SUC)
REC_ADDR «+ REC_SUC
Delete SIB_LREC(REC_ADDR) from subordinate index block buffer
else (move data block buffer back to MASTER file)
Write block at DB_ADDR from data block buffer
If MTR_ADDR = address of first record in data block buffer
thenKEY of SIB_REC(SIB_LOC) + KEY of DB_REC(
MTR_ADDR)
else Return
4. [Move subordinate index block buffer to MASTER file]
Write block at SIB_ADDR from subordinate index block buffer
Return
Tai]
4. [Finished]
Write KEY and INFO of TRAN_REC on MASTER file at location ADDR
Exit
DECLARE 1 TREC,
2 TYPE CHAR(4),
2 AMT,
3A FIXED(6,2),
3B FIXED(6,2),
3C FIXED(6,2),
3D FIXED(6,2),
2 AMTT FIXED(7,2);
/* FIRST, THE SALEMN FILE IS INITIALIZED FROM THE SALES FILE */
OPEN FILE(SALES) INPUT,
FILE(SALEMN) SEQUENTIAL OUTPUT;
SREC.FLAG = (8) '0'B;
SREC.AMT = 0;
SREC.AMTT = C;
/* READ IN INFORMATION FOR EACH SALESMAN IN THE FILE +/
ON ENDFILE(SALES) GO TO CUS;
DO WHILE('1'B);
GET FILE(SALES) EDIT(SREC.INFO.STATIC) (A(2),X(6),A(21),A(50));
WRITE FILE(SALEMN) FROM(SREC) KEYFROM(SALE¥#);
END;
CUS: CLOSE FILE(SALES), FILE(SALEMN);
S21
/* PRINT SALEMN FILE #/
OPEN FILE(SALEMN) SEQUENTIAL INPUT:
ON ENDFILE(SALEMN) GO TO OTPT1:
DO WHILE('1’B); |
READ FILE(SALEMN) INTO(SREC) KEYTO(SALE#);
PUT FILE(SYSPRINT) SKIP(2) EDIT(SREC.INFO)
(X(2),A,X(3),A(15),X(3),A(38),5(X(3),F(8,2)));
AND’,
OTPT1: CLOSE FILE(SALEMN);
END FILES:
//GO.CUST DD DSNAME=A900352.SORENSON FYL1,DISP=OLD
//GO.CUSTOM DD DSNAME=BILLING(PRIME),DISP==(NEW,DELETE),
// UNIT=SYSDA,DCB=(DSORG=IS,RKP=1,KEYLEN=5,OPTCD=L,
// CYLOFL=2),SPACE=(CYL,1)
//GO.SALES DD DSNAME=A900352.SORENSON.FYL2,DISP=OLD
//GO.SALEMN DD DSNAME=SMAN(PRIME),DISP=(NEW,DELETE),
// UNIT=SYSDA,DCB=(DSORG=IS,RKP=1,KEYLEN=3,0PTCD=L,
// CYLOFL=2),SPACE=(CYL,1)
//GO.TRANS DD DSNAME=A900352.SORENSON.FYL3,DISP=OLD
7222
EXERCISES SECTION 7-9 PAGE 750
1) The bucket capacity represents the number of records that can be inserted
into an auxiliary memory address region before an overflow takes place. If the
bucket capacity is very small (e.g., 1), then overflows are very frequent. The
time to access a record from an overflow area is excessive. On the other hand,
if the bucket capacity is large, a large amount of main memory buffer space iS
necessary to hold the contents of the bucket. In addition, the more records
there are in a bucket, the longer it takes to locate the particular record
required.
deze
3. [Scan coalescing list for empty record location]
Repeat forever
imi+l
Ifi>N
then i+ 1
Ifi = SAVE
then Write (‘FILE OVERFLOW’)
Return
else IfK, <0
then L;«+R
LINK(i) - LINK(SAVE)
LINK(SAVE) —]
Return
LINK(SAVE) + NULL
else Ksave << L;
kK; + -l
LINK(i) + NULL
Return
3. [Scan coalescing list until record or end of list found]
Repeat while i 54 NULL
i + LINK(SAVE)
If kK; = X
then K,+« -1
LINK{SAVE) + LINK(i)
LINK(i) — NULL
Return
SAVE + 1
4. [Record to be deleted not found]
Write(/RECORD NOT FOUND’)
Return
7-24
Procedure C_CL_RETRIEVE(X,R). Given a key, X, this procedure
retrieves the record identified by that key from the direct file with record
locations Lj, Log, ..., Lp.
7225
The major difference between the two techniques is that records within a
track in a record-addressable device are scanned on the basis of a key without
bringing the records into main memory. This results in a significant time
saving. With sector addressable devices, the complete sector must be brought
into main memory and records are individually examined to locate a desired
record.
In sector-addressable devices, some inter-sector space can be lost because
an integral number of records may not fit in a complete sector. This problem
is not faced in a record-addressable device.
Sector addressable devices cost less and provide reasonable performance
when many records can reside in a bucket (i.e., sector) and some overflows are
expected.
7-26
EXERCISES SECTION 7-12 PAGE 810
Vr27
For serial processing, the page frame can be thought of as a memory
buffer. Given this view, the MULTICS file system should behave in a manner
very similar to a file-based system for serial processing.
The conversion and installation of application programs should not
present any major difficulties. *
1. [Initializations|
Open MASTER file for I/O
Open TRANSACTION file for input
OLD_SEQS_ADDR + OLD_CONTI_ADDR «+ OLD_MREC_ADDR + NI
SEQS_ADDR + ADDR of IND_REC(ADDRESS)
HIGH + address of second last record at sequence set SEQGS_ADDR
720
2. [Process all transactions]
INSERT_FLAG + false
Read TRANSACTION file into TRECORD
Repeat step 3 while send of TRANSACTION file and -INSERT_FLAG
3. [Locate proper sequence set]|
Repeat while KEY of SEQ _REC(HIGH) < KEY of TRECORD
TEMP + address of last record at SEQS_ADDR
If ADDR of SEQ_REC(TEMP) = NULL
then INSERT_FLAG + true
else SEQS_ADDR «+ ADDR of SEQ_REC(TEMP)
HIGH + address of second last record at sequence
set SEQS_ADDR
(locate proper control interval)
If SEQS_ADDR = OLD_SEQS_ADDR
then SEQR_ADDR ~— OLD_SEQR_ADDR
else SEQR_ADDR + address of first record in IBeqRICAICE
set SEQS_ADDR
Repeat while KEY of SEQ_REC(SEQR_ADDR) < KEY
of TRECORD
SEQR_ADDR + address of next record in sequence
set SEQS_ADDR
CONTI_ADDR + ADDR of SEQ_REC(SEQR_ADDR)
(locate proper record)
If CONTI_ADDR = OLD_CONTI_ADDR
then MREC_ADDR + OLD_MREC_ADDR
else MREC_ADDR + address of first record in control
interval CONTI_LADDR
Repeat while KEY of MRECORD(MREC_ADDR) < KEY
of TRECORD .
MREC_ADDR + address of next record in control
interval CONTI_ADDR
(process the transaction)
Process transaction against MRECORD(MREC_ADDR)
(prepare for next transaction)
OLD_SEQS_ADDR + SEQS_ADDR
OLD_CONTI_ADDR + CONTI_ADDR
OLD_MREC_ADDR «+ MREC_ADDR
4. [Expected insertion transaction]
If INSERT_FLAG
then Repeat while ~end of TRANSACTION file
If TYPE of TRECORD $ insertion
then Write(/INVALID TRANSACTION’)
else Process insertion transaction
Read TRANSACTION file into TRECORD
IELo
5. [Finished]
Close MASTER file
Close TRANSACTION file
Return
1. [Initializations]
Open MASTER file
Read TRECORD
2. [Insertion at end of MASTER file?]
TEMP + address of last record in index set
If KEY of TRECORD > KEY of IND_REC(TEMP)
then If TYPE of TRECORD ea insertion
then Write(/INVALID TRANSACTION’)
Return
else TEMP + ADDR of IND_REC(TEMP)
ADDRESS + address of second last record in sequence
set TEMP
TEMP + ADDR of SEQ_REC(ADDRESS)
ADDRESS + address of first free space in control
interval TEMP
Process transaction against ep oer ene)
Return
3. (Locate pproper sequence set]
Repeat while KEY of IND_REC(ADDRESS) < KEY of TRECORD
ADDRESS + address of next record in index set
TEMP + ADDR of IND_REC(ADDRESS)
4. [Locate proper control interval]
ADDRESS + address of first record in sequence set TEMP
Repeat while KEY of SEQ_REC(ADDRESS) < KEY of TRECORD
ADDRESS + address of next record in sequence set TEMP
TEMP + ADDR of SEQ_REC(ADDRESS)
= [Locate proper record]
ADDRESS + address of first record in control area TEMP
Repeat while KEY ofMRECORD(ADDRESS) < KEY of TRECORD
ADDRESS + address of next record in control area TEMP
6. [Process the transaction]
Process transaction against MRECORD(ADDRESS)
Return
7-30
5) The basic advantages of a key-sequenced VSAM file over an IBM indexed
sequential file are:
— dynamic processing capabilities
— garbage collection which recovers space from deletion and updates
which yield a shorter record length.
— insertions never go into overflow area (a responsibility of user in
IBM IS files); therefore a simple access algorithm.
— additional access nodes
— skip sequential
— relative byte
— the average access time for a single record in a VSAM file is less than
that of an IBM IS file. This is because of the linear search required for
records in the overflow are.
Of course there are disadvantages in choosing a VSAM file over IBM IS file:
La
EXERCISES SECTION 7-13 PAGE 825
1) Two tables are required in our general multilist structure: the secondary index
table, and the info/field corrélation table. Examples below are given to
demonstrate their use in accessing a record.
‘name!
G# ‘ward!
‘dummy’
1332
The Info/Field correlation table is responsible via the BEGIN field for
identifying a range in the secondary index table for each category. The
FIELD field points out which INFO in the record contains the GENERAL
category.
Recall the example query: ‘‘List the names of all patients in the general
ward who are taking (the drug) CYROL.” In this case ‘ward general”, and
“drug CYROL” correspond to X and Y, and ‘‘name”’ corresponds to the
output Z. Note ‘‘drug’’, ‘‘ward”, and ‘‘name”’ are the general categories
whereas ‘‘general’’ and ‘‘CYROL”’ are the particular values. Therefore we
shall assumed from some sort of query scanner, the following input:
_ an array, G, of subscripts into the info/field correlation table.
_ an array, P, of character strings, supposedly properties in the secondary
index table.
— an index, N, which gives the size of array P (and also determines the size
of array G = N + 1). By virtue of the query we expect P[I] (1 <1 <
N) to be a property of the general category GENERAL.
Usually the problem is well enough defined or constrained that the general
categories are known a priori. Then the logic of the algorithm is modified so
that the info/field correlation table is not required, and the proper secondary
index table is automatically searched. A particular item value will suffice
alone in such a query because the category is assumed.
230
2. [Chain down list of shortest length]
NEXT + PKEY|[SHORT]
P[SHORT] + P[N]
G[SHORT] — G[N]
EMPTY_SET < true
Repeat while NEXT 4 NULL (more records in shortest list)
Read RECORD(NEXT)
|iets
(check if all other properties hold)
Repeat while I < N and INFO(FIELD[G[I]]) of RECORD(NEXT) =: Pil]
eae
Ifl=N
then Write INFO(FIELD[G[N+1]]) of RECORD(NEXT)
EMPTY_SET + false
NEXT «+ LINK(FIELD[G[N]]) of RECORD({NEXT)
3. [Any records satisfy conditions?|
If EMPTY_SET
then Write(/NO RECORDS SATISFY ALL CONDITIONS’)
Return
bo In the general inverted list structure, two tables are required: the inverted list
and the property table.
7-34
Procedure INVERTLIST(X,Y,Z). Given the tables of the inverted list
structure and the character strings, X, Y, and Z, this procedure outputs
information Z for all records with properties described by X and Y. INFO(Z)
is the file which contains information Z; PROP# gives the number of
properties in the property table. Temporary variables are: TEMP, J, BA, BB,
EA, and EB, indices into the property table, and EMPTY_SET, a boolean
variable.
1335
4. [Any records satisfy both properties?|
If EMPTY_SET
then Write(’NO ITEM SATISFIES BOTH PROPERTIES’)
Return
Ms [J
B + BEGIN[G[]]]
EB — BEGIN(G[I] + 1) -1
Repeat while B < E and -(PARTICULAR|B] satisfies P[]])
Ba Bi I
ff Bo > E
then Write('NO SUBSET OF PROPERTY APPLIES’)
Return
If LENGTHIB] ...
[..4 then
Read RECORD(NEXT)
eat
Repeat while I < N and INFO(FIELD[G[I]]) of RECORD(NEXT) satisfies P[]]
l—1+a
Ifil>N
then Output INFO(FIELD[G[N+]]}) ...
7-36
An example of the controlled list-length multilist follows:
‘35!
'50
‘90! mem
to
© W
PKEY 8437 is a primary key for the head of a chain of records with age field
item in range 50-89
In our example using cellular serial access, two tables are required:
cell 1
ToT.
Procedure CELLULAR_SERIAL(X,Y,Z). Given the cellular-serial
structure as previously described, and the character strings, X, Y, and Z, this
procedure outputs information from the INFO({Z) field of all records with
properties X and Y. This procedure is similar to both procedures MULTILIST
and INVERTLIST, so most of the variables used are previously discussed. S is
the index of an entry in the cell table (whose LENGTH field is minimal), PL is
the index of an entry in the property table, and FL is the field of a record
which contains the category of PROPERTY[PL]. Generally, S implies short,
L implies long for variable names.
0559
Procedure MULTI_& INVERT(A,B). Given A, the subscript to an
entry in the property list which corresponds to a range in the inverted list,
and B, the subscript of an entry in the multilist index, this procedure outputs
information from all the records with PROPERTY|A] of the property table
and PROPERTY|B] of the multilist index. Variable names and notation will
be as in the earlier exercises in this section.
1. [Initializations]
BA + BEGIN|A]
EA + END[A]
NEW_KEY + PRINT_KEY[B] of multilist index
L + LENGTHIB] of multilist
EMPTY_SET < true
2. [Read all records which have been proved to be necessary]
Repeat while BA < EA and L > 0
If PRIME_KEY|[BA] of invert list = NEW_KEY
then Read RECORD(NEW_KEY)
Output desired information from record
NEW_KEY + LINK(NEW_KEY)
BA — BA +1
L+L-1
EMPTY_SET + false
If PRIME_KEY[BA] of invert list < NEW_KEY
then BA «+ BA+1
else IfL=1
then L+0O
else IfL<EA-BA+1
then Read RECORD(NEW_KEY)
NEW_KEY + LINK(NEW_KEY)
L+L-l
else Read RECORD(PRIME_KEY|BA]) of
inverted list
If INFO(PRIME_KEY|BA])=PROPERTY
[B] of multilist index
_then
Output desired information
EMPTY_SET + false
NEW_KEY + LINK(PRIME_KEY!?A])
BA + BA +1
3. [Any information displayed?]
If EMPTY_SET
then Write(/NO RECRODS SATISFY BOTH PROPERTIES’)
Return
7-40
6) An involute structure has all the advantages and disadvantages of the
multilist structure and the following:
advantages: Most efficient use of storage (warranted when knowledge of
a secondary index item is not required at involute record level)
disadvantages: It is difficult, time-consuming, and costly (but not
impossible) to determine a secondary index item of an involute record
A very good structure when answering question such as ‘‘Does property X,
property Y, etc. hold for a databox?”’.
1: [Initializations]
RESULT + 0
2: [For each property isolate the range in the inverted list]
Repeat for I = 1, 2, ..., N
J+1
Repeat while J < P# and x, P{J]
J+ J+1
If J > P#
then Write(‘INVALID PROPERTY’)
Return(0)
Bil] — BEGIN|J]
E[I] — END[J]
[Compare entries of each property range to the first property range]
Repeat thru step 8 while B[I] < E[I]
[Look for common entry in all ranges]
I+2
Repeat thru step 7 while I < N
[Isolate location of expected entry]
Repeat while B[I] < E[I] and PKEY(B[!]) < PKEY(B[1])
B{I] — Bil] + 1
[End of property range?|
If Bil] > Ey]
then Return(RESULT)
{Matching primary keys?|
If PKEY(B[I]) = PKEY(B[1))
then I+I+1
else Repeat while B[1] < E[1] and PKEY(B[1]) < PKEY(BJ}])
Bil] + Bil] + 1
7-41
If Bil] > E[1]
then Return(RESULT)
else [+2
8. [All property ranges have primary key in common]
RESULT « RESULT + 1
Bi1] — Bil] + 1
I+ 2
9. [Finished]
Return(RESULT)
,
7-42