Sie sind auf Seite 1von 66

Solutions to Exercises

1.1

#include <iostream.h> intmain (void) { double fahrenheit ; double cels ius; cout << "Temperature inFahrenhait "; : cin >> fahrenheit ; cels = 5 * (fahrenheit-32) /9; ius cout << fahrenheit<< "degrees Fahrenheit= " << cels << "degrees Celsius\n" ius ; return0; }

1.2

intn = 100; unsigned inti= 100; signed int= 2.9; long m = 2,p = 4; int 2k; double x = 2 * m; f loaty = y * 2; unsigned double z = 0.0; double d = 0.67F; f loatf= 0.52L; signed char = 1786; char c = '$' 2; + sign char h = ' \111' ; char *name = "PeterPan"; unsigned char *num = "276811"; identi i r fe seven_11 _unique_ grossincome gross$income 2by2 default average_weight_of_a_ large_pizza variable object iented .or

/ val / id / val / id / invalid:no variablename / / val / id / invalid:2k not an ident f e / ii r / val / id / val (butdangerous!) / id / invalid:can'tbe unsigned / / val / id / val / id / invalid:no variablename / / val / id / invalid:'s not recognized / ign' / val / id / val / id / val / id / val / id / val / id / invalid:-not al / lowed inid / invalid:$ not al / lowed inid / invalid:can'tstartwith digi / t / invalid:defaultisa keyword / / val / id / val / id / invalid:.not al / lowed inid

1.3

230

C++ Programming

Copyright 1998 Pragmatix Software

1.4

int age; double employeeIncome; longwordsInDictn; charlet ; ter char*greet ing;

/ age ofa person / / employee income / / number ofwords indict / ionary / let ofalphabet / ter / greetingmessage /

2.1

/ testi n iseven: / f n%2 == 0 / testi c isa digi : / f t c >= '0 && c <= '9 ' ' / testi c isa let : / f ter c >= 'a && c <= 'z | c >= 'A'&& c <= 'Z' ' '| / testi n isodd and posit or n iseven and negative: / f ive n%2 != 0 && n >= 0 | n%2 == 0 && n < 0 | / setthe n- bitofa long integer fto1: / th f|= (1L << n) / resetthe n- bitofa long integer fto0: / th f&= ~(1L << n) / give the absolutevalue ofa number n: / (n >= 0 ? n :n) / give the number ofcharactersina nullterminated str l te l / ing i ra s: sizeof(s -1 ) (( <= (p + q))&& (n >= (p -q)))| (n == 0)) (n | (( (++n) * (q-))/((++p) -q)) (n |((p& q) ^ (p << (2 + q))) ) ((p< q) ? ((n< p) ? ((q* n) -2) :((q/n) + 1)):(q -n)) double d = 2 * int .14) (3 ; longk = 3.14 -3; charc = 'a + 2; ' charc = 'p' 'A'-'a ; + ' #include <iostream.h> intmain (void) { long n; cout << "What isthe value ofn? "; cin >> n; cout << "2 tothe power of"<< n << "= "<< (1L << n) << ' ' \n ; return0; } / ini i l z d to6 / t a i es / ini i l z k to0 / t a i es / ini i l z c to'c / t a i es ' / ini i l z c to'P / t a i es '

2.2

2.3

2.4

2.5

#include <iostream.h> intmain (void) { double n1,n2,n3; cout << "Inputthree numbers:"; cin >> n1 >> n2 >> n3;

231

C++ Programming

Copyright 1998 Pragmatix Software

cout << (n1 <= n2 && n2 <= n3 ? "Sorted":"Notsorted")<< ' ' \n ; return0; }

3.1

#include <iostream.h> intmain (void) { double height,weight; cout << "Person'sheight( centimeters) "; in : cin>> height; cout << "Person'sweight( ki in lograms:"; cin>> weight; i (weight< height/2.5) f cout<< "Underweight\n" ; elsei (height/2 <= weight&& weight<= height/2.3) f .5 cout<< "Normal\n"; else cout<< "Overweight\n" ; return0; }

3.2

It will output the message n isnegative. This is because the else clause is associated with the if clause immediately preceding it. The indentation in the code fragment
i (n >= 0) f i (n < 10) f cout << "n issmall ; \n" else cout<< "n isnegative\n" ;

is therefore misleading, because it is understood by the compiler as:


i (n >= 0) f i (n < 10) f cout << "n issmall ; \n" else cout << "n isnegative\n";

The problem is fixed by placing the second if within a compound statement:


i (n >= 0) { f i (n < 10) f cout << "n issmall ; \n" } else cout<< "n isnegative\n" ;

www.pragsoft.com

Solutions to Exercises

232

3.3

#include <iostream.h> intmain (void) { intday,month,year; char ch; cout << "Inputa date as dd/mm/yy:"; cin>> day >> ch >> month >> ch >> year; switch (month){ case 1: cout<< "January";break; case 2: cout<< "February"; break; case 3: cout<< "March"; break; case 4: cout<< "Apri " l; break; case 5: cout<< "May"; break; case 6: cout<< "June"; break; case 7: cout<< "Ju ; ly" break; case 8: cout<< "August";break; case 9: cout<< "September"; break; case 10: cout<< "October"; break; case 11: cout<< "November"; break; case 12: cout<< "December"; break; } cout << ''<< day << ","<< 1900 + year << ' ' \n ; return0; }

3.4

#include <iostream.h> intmain (void) { intn; intfactor l 1; ia = cout << "Inputa posit integer:"; ive cin>> n; i (n >= 0) { f for(registerinti= 1;i<= n;++i) factor l i ia *= ; cout<< "Factor l "<< n << "= "<< factor l ' ' ia of ia << \n ; } return0; }

3.5

#include <iostream.h> intmain (void) { intoctal digi ; , t intdecimal= 0; int power = 1;

233

C++ Programming

Copyright 1998 Pragmatix Software

cout << "Inputan octalnumber:"; cin>> octal ; for( n = octal n > 0;n /= 10) { / process each digi int ; / t digi = n % 10; t / rightmost digi / t decimal= decimal+ power * digi ; t power *= 8; } cout << "Octal " ( << octal<< ")= Decimal("<< decimal<< ") ; \n" return0; }

3.6

#include <iostream.h> intmain (void) { for(regis i= 1;i<= 9;++i) ter for(registerj= 1;j<= 9;++j) cout << i<< "x "<< j<< "= "<< i* << ' ' j \n ; return0; }

4.1a

#include <iostream.h> double FahrenToCelsius(doublefahren) { return5 * (fahren -32) /9; } intmain (void) { double fahrenheit ; cout << "Temperature inFahrenhait "; : cin >> fahrenheit ; cout << fahrenheit<< "degrees Fahrenheit= " << FahrenToCelsius( fahrenheit << "degrees Celsius\n" ) ; return0; }

4.1b

#include <iostream.h> char*CheckWeight (doubleheight,double weight) { i (weight< height/2.5) f return"Underweight" ; i (height/2 <= weight&& weight<= height/2.3) f .5 return"Normal"; return"Overweight" ; }

www.pragsoft.com

Solutions to Exercises

234

intmain (void) { double height,weight; cout << "Person'sheight( centimeters) "; in : cin>> height; cout << "Person'sweight( ki in lograms:"; cin>> weight; cout << CheckWeight(height weight)<< ' ' , \n ; return0; }

4.2

The value of x and y will be unchanged because Swap uses value parameters. Consequently, it swaps a copy of x and y and not the originals. The program will output:
Parameter Local Global Parameter

4.3

4.4

enum Bool{false,true}; void Primes (unsigned intn) { BoolisPr ime; for(regis num = 2;num <= n;++num) { ter isPr ime = true; for(registeri= 2;i< num/2;++i) i (num%i == 0) { f isPr ime = false; break; } i ( ime) f isPr cout << num << ' ' \n ; } }

4.5

enum Month { Jan,Feb,Mar,Apr,May, Jun, Ju , l Aug, Sep,Oct,Nov,Dec }; char*MonthStr(Month month) { switch (month){

235

C++ Programming

Copyright 1998 Pragmatix Software

case Jan:return"January"; case Feb:return"february"; case Mar: return"March"; case Apr:return"Apri " l; case May: return"May"; case Jun:return"June"; case Ju : return"Ju ; l ly" case Aug: return"August"; case Sep: return"September"; case Oct:return"October"; case Nov: return"November"; case Dec: return"December"; default return""; : } }

4.6

inl intIsAlpha (charch) ine { returnch >= 'a && ch <= 'z | ch >= 'A'&& ch <= 'Z' ' '| ; } intPower ( base,unsigned intexponent) int { return(exponent <= 0) ?1 :base * Power(base,exponent -1); } double Sum ( n,double val. . int .) { va_l t is args; / argument l s / it double sum = 0; va_start (args val) , ; / ini i l z args / t ai e

4.7

4.8

while(n- > 0) { sum += val; val= va_arg(args,double); } va_end(args) ; returnsum; } / clean up args /

5.1

void ReadArray (double nums[],constintsize) { for(regis i= 0;i< size;++i){ ter cout<< "nums["<< i<< "]= "; cin>> nums[i] ; } }

www.pragsoft.com

Solutions to Exercises

236

void WriteArray(double nums[],constintsize) { for(regis i= 0;i< size;++i) ter cout<< nums[i]<< ' ' \n ; }

5.2

void Reverse (double nums[],constintsize) { double temp; for(regis i= 0;i< size/2;++i){ ter temp = nums[i] ; nums[i]= nums[size-i-1]; nums[size-i-1] = temp; } }

5.3

double contents[] = { [4] { 12,25,16,0.4 }, { 22, 4, 8,0.3 }, { 28, 5, 9,0.5 }, { 32, 7, 2,0.2 } }; void WriteContents(constdouble *contents, constintrows,constintcols) { for(regis i= 0;i< rows;++i) { ter for(registerj= 0;j< cols; ++j) cout << *(contents+ i* rows + j << '' ) ; cout<< ' ' \n ; } }

5.4

enum Bool{false,true}; void ReadNames (char*names[], constintsize) { char name[128]; for(regis i= 0;i< size;++i){ ter cout<< "names["<< i<< "]= "; cin>> name; names[i]= new char[st l r en(name) + 1]; strcpy(names[i , ]name); } } void WriteNames (char*names[], constintsize) { for(regis i= 0;i< size;++i) ter

237

C++ Programming

Copyright 1998 Pragmatix Software

cout<< names[i]<< ' ' \n ; } void BubbleSort(char*names[], constintsize) { Boolswapped; char *temp; do { swapped = false; for(registeri= 0;i< size-1;++i){ i (strcmp(names[i] names[i+1])> 0 ){ f , temp = names[i] ; names[i]= names[i+1]; names[i+1]= temp; swapped = true; } } } while(swapped); }

5.5

char*ReverseStr (char*str ing ) { intlen = str len(st ) r; char *resul = new char[ + 1]; t len char *res= result len; + *res- = ' ' - \0 ; while(*str ) *res- = *str++; returnresult ; }

5.6

typedefint(*Compare)(constchar*,constchar*) ; void BubbleSort(char*names[], constintsize,Compare comp) { Boolswapped; char *temp; do { swapped = false; for(registeri= 0;i< size-1;++i){ i (comp(names[i] names[i+1])> 0 ){ f , temp = names[i] ; names[i]= names[i+1]; names[i+1]= temp; swapped = true; } } } while(swapped); }

www.pragsoft.com

Solutions to Exercises

238

5.7

typedefvoid (*SwapFun)(double,double); SwapFun Swap; typedefchar *Table[] ; Table table; typedefchar *&Name; Name name; typedefunsigned long *Values[10][20] ; Values values;

6.1

Declaring Set parameters as references avoids their being copied in a call. Call-by-reference is generally more efficient than call-by-value when the objects involved are larger than the built-in type objects.
classComplex { public : Complex (doubler= 0,double i= 0) {real= r;imag = i ;} Complex Add (Complex &c); Complex Subtract(Complex &c); Complex Mult ly ip (Complex &c); void Print (void) ; private: double real / realpart ;/ doubleimag; / imaginarypart / }; Complex Complex::Add (Complex &c) { returnComplex(real+ c.real imag + c. , imag); } Complex Complex::Subtract(Complex &c) { returnComplex(real-c.real imag -c. , imag); } Complex Complex::Mult ly(Complex &c) ip { returnComplex( real* c.real-imag * c. imag, imag * c.real+ real* c. imag); } void Complex::Pr t in (void) { cout << real<< "+ i"<< imag << ' ' \n ; }

6.2

6.3

#include <iostream.h> #include <string.h> constintend = 1; / denotes the end ofthe l s / it

239

C++ Programming

Copyright 1998 Pragmatix Software

classMenu { public : Menu (void) {fi t 0;} rs = ~Menu (void) ; voidInsert (constchar *str constintpos = end); , voidDelete (constintpos = end); int Choose (void) ; private: classOption { public : Option (constchar*) ; ~Option (void) {deletename;} constchar* Name (void) {returnname;} Option*& Next(void) {returnnext;} private: char*name; / optionname / Option *next; / next option / }; Option }; Menu::Option: :Opt (constchar*str) ion { name = new char [st len(st ) 1]; r r+ strcpy(name, str ; ) next = 0; } Menu::~Menu (void) { Menu::Option*handy,*next; for(handy = f rs ; i thandy != 0;handy = next){ next = handy->Next() ; deletehandy; } } void Menu:: Insert(constchar *str constintpos) , { Menu::Option*option= new Menu::Option(st ) r; Menu::Option*handy,*prev = 0; int = 0; idx / setprev topointtobeforethe insert posit / ion ion: for(handy = f rs ; i thandy != 0 && idx++ != pos;handy = handy->Next() ) prev = handy; i (prev == 0) { f / empty l s / it option>Next()= f rs ; / i s entry i t/ f r t f r t option; i s= *f r t i s; /frt / i s option inthe menu

www.pragsoft.com

Solutions to Exercises

240

} else{ / insert / option>Next()= handy; prev>Next()= option; } } void Menu::Delete(constintpos) { Menu::Option*handy,*prev = 0; int = 0; idx / setprev topointtobeforethe delet posit / ion ion: for(handy = f rs ; i t handy != 0 && handy->Next()!= 0 && idx++ != pos; handy = handy->Next()) prev = handy; i (handy != 0) { f i (prev == 0) f / i ' the f r t / ts i s entry f r t handy->Next() i s= ; else / i ' not the f rs / ts i t prev>Next()= handy->Next() ; deletehandy; } } intMenu::Choose (void) { intn,choice; Menu::Option*handy = f r t i s; do { n = 0; for(handy = f r thandy != 0;handy = handy->Next() i s; ) cout << ++n << "."<< handy->Name() << ' ' \n ; cout<< "Option?"; cin>> choice; } while(choice<= 0 | choice > n); | returnchoice; }

6.4

#include <iostream.h> constint maxCard = 10; enum Bool {false,true};

classSet { public : Set ~Set int Card (void) (void) ; (void) ; { f r t 0;} i s=

241

C++ Programming

Copyright 1998 Pragmatix Software

Bool Member voidAddElem void RmvElem void Copy Bool Equal void Intersect voidUnion void Print private: classElement { public : int Element*& private: int Element }; Element *f r t i s; };

(constint ) (constint ; ) (constint ; ) (Set&); (Set&); (Set&,Set&); (Set&,Set&); (void) ;

const;

Element (constintval) {value = val;next = 0;} Value (void) {returnvalue;} Next (void) {returnnext;} value; *next; / element value / / next element /

/ f rs element inthe l s /i t it

Set: :~Set(void) { Set: lement *handy,*next; :E for(handy = f rs ; i thandy != 0;handy = next){ next = handy->Next() ; deletehandy; } } intSet: :Card(void) { Set: lement *handy; :E int card = 0; for(handy = f rs ; i thandy != 0;handy = handy->Next()) ++card; returncard; } BoolSet: :Member (constintelem) const { Set: lement *handy; :E for(handy = f rs ; i thandy != 0;handy = handy->Next()) i (handyf >Value()== elem) returntrue; returnfalse; }

www.pragsoft.com

Solutions to Exercises

242

void Set: :AddElem (constintelem) { i (!Member(elem)){ f Set: lement *option= new Set: lement(elem); :E :E option>Next()= f r t i s; / prepend / f rs = option; i t } } void Set: :RmvElem (constintelem) { Set: lement *handy,*prev = 0; :E int = 0; idx / setprev topointtobeforethe delet posit / ion ion: for(handy = f rs ; i t handy != 0 && handy->Next()!= 0 && handy->Value()!= elem; handy = handy->Next()) prev = handy; i (handy != 0) { f i (prev == 0) f / i ' the f r t / ts i s entry f r t handy->Next() i s= ; else / i ' not the f rs / ts i t prev>Next()= handy->Next() ; deletehandy; } } void Set: :Copy (Set&set) { Set: lement *handy; :E for(handy = f rs ; i thandy != 0;handy = handy->Next()) set.AddElem(handy>Value()) ; } BoolSet: :Equal(Set&set) { Set: lement *handy; :E i (Card()!= set.Card() f ) returnfalse; for(handy = f rs ; i thandy != 0;handy = handy->Next()) i (!set f .Member(handy>Value()) ) returnfalse; returntrue; } void Set: In : tersect(Set&set,Set &res) { Set: lement *handy; :E for(handy = f rs ; i thandy != 0;handy = handy->Next())

243

C++ Programming

Copyright 1998 Pragmatix Software

i (set f .Member(handy>Value()) ) res.AddElem(handy>Value()) ; } void Set: :Union (Set&set,Set &res) { Copy(res) ; set.Copy(res) ; } void Set: in (void) :Pr t { Set: lement *handy; :E cout << '{' ; for(handy = f rs ; i thandy != 0;handy = handy->Next()) { cout << handy->Value() ; i (handyf >Next()!= 0) cout << ' ' ,; } cout << "}\n"; }

6.5

#include <iostream.h> #include <string.h> enum Bool{false,true}; typedefchar *Str ing; classBinNode; classBinTree; classSequence { public : Sequence (constintsize) ; ~Sequence (void) {deleteentr ;} ies void Insert (constchar*) ; void Delete (constchar*) ; Bool Find (constchar*) ; void Print (void) ; int Size (void) {returnused;} fr iend BinNode* BinTree: :MakeTree (Sequence &seq,intlow,inthigh); protected: char constint int };

**entr ; ies slots ; used;

/ sorted array ofstr entr / ing ies / number ofsequence slots / / number ofslotsused so far /

void Sequence:: Insert (constchar *str ) { i (used >= slots) f

www.pragsoft.com

Solutions to Exercises

244

return; for(registeri= 0;i< used;++i) { i (strcmp(str f ,entr [ ]< 0) ies i ) break; } for(registerj= used;j> i -j ;- ) entr j= entr j ]; ies[ ] ies[ 1 entr i= new char[st l t ) 1]; ies[ ] r en(s r + strcpy(entr i , ; ies[ ]str) ++used; } void Sequence::Delete(constchar *str ) { for(registeri= 0;i< used;++i) { i (strcmp(str f ,entr [ ]== 0) { ies i ) deleteentr i ; ies[ ] for(registerj= i j< used- ++j) ; 1; entr j= entr j+1]; ies[ ] ies[ -used; break; } } } Bool Sequence::F (constchar *str ind ) { for(registeri= 0;i< used;++i) i (strcmp(str f ,entr [ ]== 0) ies i ) returntrue; returnfalse; } void Sequence::Pr t in (void) { cout << ' ' [; for(registeri= 0;i< used;++i) { cout << entr i ; ies[ ] i ( < usedfi 1) cout << ' ' ,; } cout << "] ; \n" }

6.6

#include <iostream.h> #include <string.h> enum Bool{false, rue}; t classBinNode {

245

C++ Programming

Copyright 1998 Pragmatix Software

public : BinNode (constchar*) ; ~BinNode (void) {deletevalue;} char*& Value (void) {returnvalue;} BinNode*& Left (void) {returnlef ;} t BinNode*& Right (void) {returnr ight ;} void FreeSubtree (BinNode *subtree); void InsertNode (BinNode *node,BinNode *&subtree); void DeleteNode (constchar*,BinNode *&subtree); constBinNode* FindNode (constchar*,constBinNode *subtree); void PrintNode (constBinNode *node); private: char*value; BinNode *lef ; t BinNode *r ight ; };

/ node value / / pointertolef chi / t ld / pointertorightchi / ld

classBinTree { public : BinTree (void) {root= 0;} BinTree(Sequence &seq); ~BinTree(void) {root>FreeSubtree(root) ;} voidInsert (constchar *str ; ) void Delete (constchar *str {root) >DeleteNode(str root) , ;} BoolFind (constchar *str {returnroot) >FindNode(str root)!= 0;} , voidPrint (void) {root>PrintNode(root) cout<< ' ' ; \n ;} protected: BinNode* root; };

/ rootnode ofthe tree /

BinNode::BinNode (constchar*str ) { value = new char[st l t ) 1]; r en(s r + strcpy(value,str) ; lef = r t ight= 0; } void BinNode::FreeSubtree (BinNode *node) { i (node != 0) { f FreeSubtree(node>left ; ) FreeSubtree(node>right) ; deletenode; } } void BinNode:: InsertNode (BinNode *node,BinNode *&subtree) { i (subtree == 0) f

www.pragsoft.com

Solutions to Exercises

246

subtree = node; elsei (strcmp(nodef >value,subtree>value)<= 0) InsertNode(node,subtree>left ; ) else InsertNode(node,subtree>right) ; } void BinNode::DeleteNode (constchar *str BinNode *&subtree) , { intcmp; i (subtree == 0) f return; i ((cmp = strcmp(str subtreef , >value))< 0) DeleteNode(str subtree, >left) ; elsei (cmp > 0) f DeleteNode(str subtree, >right) ; else{ BinNode* handy = subtree; i (subtreef >left== 0) / no lef subtree / t subtree = subtree>right; else i (subtreef >right== 0) / no r / ightsubtree subtree = subtree>left ; else { / lef and rightsubtree / t subtree = subtree>right; / insertlef subtree intorightsubtree: / t InsertNode(subtree>left subtree, >right) ; } deletehandy; } } constBinNode* BinNode::F indNode (constchar *str constBinNode *subtree) , { intcmp; return(subtree == 0) ?0 :((cmp = strcmp(str subtree, >value))< 0 ? FindNode(str subtree, >left ) :(cmp > 0 ? FindNode(str subtree, >right) :subtree)) ; } void BinNode::Pr tNode (constBinNode *node) in { i (node != 0) { f PrintNode(node>left ; ) cout<< node->value << '' ; PrintNode(node>right) ;

247

C++ Programming

Copyright 1998 Pragmatix Software

} } BinTree: inTree (Sequence &seq) :B { root= MakeTree(seq,0,seq.Size() 1); } void BinTree: Inser (constchar *str : t ) { root>InsertNode(new BinNode(str , )root) ; }

6.7

classSequence { / .. /. fr iend BinNode* BinTree: :MakeTree (Sequence &seq,intlow,inthigh); }; classBinTree { public : / .. /. BinTree(Sequence &seq); / .. /. BinNode* MakeTree (Sequence &seq,intlow,inthigh); }; BinTree: inTree (Sequence &seq) :B { root= MakeTree(seq,0,seq.Size() 1); } BinNode* BinTree: :MakeTree (Sequence &seq,intlow,inthigh) { intmid = ( + high)/2; low BinNode* node = new BinNode(seq.entr [mid]) ies ; node->Left( = (mid == low ? 0 :MakeTree(seq,low,mid-1)); ) node->Right()= (mid == high ? 0 :MakeTree(seq,mid+1, high)) ; returnnode; }

6.8

A static data member is used to keep track of the last allocated ID (see last below). Id
classMenu { public : / .. /. int ID private: / .. /. int id;

(void)

{returnid;}

/ menu ID /

www.pragsoft.com

Solutions to Exercises

248

stat int ic };

last ; Id

/ lastal / located ID

intMenu:: Id= 0; last

6.9

#include <iostream.h> #include <string.h> constintend = 1; classOption; classMenu { public : Menu (void) {fi t 0;id= last rs = Id++;} ~Menu (void) ; voidInsert (constchar *str constMenu *submenu, constintpos = end); , voidDelete (constintpos = end); int Print (void) ; int Choose (void) const; int ID (void) {returnid;} private: classOption { public : Option (constchar*,constMenu* = 0); ~Option (void) ; constchar* Name (void) {returnname;} constMenu* Submenu (void) {returnsubmenu;} Option*& Next (void) {returnnext;} void Print (void) ; int Choose (void) const; private: char *name; / optionname / constMenu *submenu; / submenu / Option *next; / next option / }; Option *f r t i s; int id; stat int ic }; last ; Id / f rs optioninthe menu /i t / menu ID / / lastal / located ID / denotes the end ofthe l s / it

Menu::Option: :Opt (constchar*str constMenu *menu) :submenu(menu) ion , { name = new char [st len(st ) 1]; r r+ strcpy(name, str ; ) next = 0; } Menu::Option: :~Option (void) {

249

C++ Programming

Copyright 1998 Pragmatix Software

deletename; deletesubmenu; } void Menu::Option: r t :P in (void) { cout << name; i (submenu != 0) f cout << ">"; cout << ' ' \n ; } intMenu::Option: :Choose (void)const { i (submenu == 0) f return0; else returnsubmenu->Choose(); } intMenu:: Id= 0; last Menu::~Menu (void) { Menu::Option*handy,*next; for(handy = f rs ; i thandy != 0;handy = next){ next = handy->Next() ; deletehandy; } } void Menu:: Insert(constchar *str constMenu *submenu, constintpos) , { Menu::Option*option= new Option(strsubmenu); , Menu::Option*handy,*prev = 0; int = 0; idx / setprev topointtobeforethe insert posit / ion ion: for(handy = f rs ; i thandy != 0 && idx++ != pos;handy = handy->Next() ) prev = handy; i (prev == 0) { f / empty l s / it option>Next()= f rs ; / i s entry i t/ f r t f r t option; i s= } else{ / insert / option>Next()= handy; prev>Next()= option; } } void Menu::Delete(constintpos) { Menu::Option*handy,*prev = 0;

www.pragsoft.com

Solutions to Exercises

250

int = 0; idx / setprev topointtobeforethe delet posit / ion ion: for(handy = f rs ; i t handy != 0 && handy->Next()!= 0 && idx++ != pos; handy = handy->Next()) prev = handy; i (handy != 0) { f i (prev == 0) f / i ' the f r t / ts i s entry f r t handy->Next() i s= ; else / i ' not the f rs / ts i t prev>Next()= handy->Next() ; deletehandy; } } intMenu::Pr t in (void) { intn = 0; Menu::Option*handy = f r t i s; for(handy = f rs ; i thandy != 0;handy = handy->Next()) { cout<< ++n << "."; handy->Print( ; ) } returnn; } intMenu::Choose (void)const { intchoice,n; do { n = Print ) (; cout<< "Option?"; cin>> choice; } while(choice<= 0 | choice > n); | Menu::Option*handy = f r t i s; n = 1; / move tothe chosen option: / for(handy = f rs ; != choice && handy != 0;handy = handy->Next()) i tn ++n; / choose the option: / n = handy->Choose(); return(n == 0 ? choice:n); }

7.1
251

#include <str ing.h>

C++ Programming

Copyright 1998 Pragmatix Software

constintMax (constintx,constinty) { returnx >= y ? x :y; } constdouble Max (constdouble x,constdouble y) { returnx >= y ? x :y; } constchar* Max (constchar *x,constchar *y) { returnstrcmp(x,y)>= 0 ? x :y; }

7.2

classSet { / .. /. fr iend Set operatorfr iend Bool operator<= / .. /. };

(Set&,Set&); (Set&,Set&);

/ dif / ference / subset /

Set operator-(Set&set1,Set &set2) { Set res; for(regis i= 0;i< set1.card;++i) ter i (!(set1.e f lems[i & set2)) ] res.e lems[res.card++] = set1.e lems[i ; ] returnres; } Booloperator<= (Set&set1,Set &set2) { i (set1.card> set2.card) f returnfalse; for(regis i= 0;i< set1.card;++i) ter i (!(set1.e f lems[i & set2)) ] returnfalse; returntrue; }

7.3

classBinary { / .. /. fr iend Binary int / .. /. };

operator(constBinary,constBinary); operator[] (constintn) {returnbits[15- == '1 ? 1 :0;} n] '

Binary operator-(constBinary n1,constBinary n2) {

www.pragsoft.com

Solutions to Exercises

252

unsigned borrow = 0; unsigned value; Binary res= "0"; for(regis i= 15;i>= 0;-i { ter -) value = (n1.bi [ ] ts i== '0' 0 :1) ? (n2.bi [ ] ts i== '0 ? 0 :1) + borrow; ' res.b ts i= (value == - | value == 1 ? '1 : ) i [] 1 | ' '0' ; borrow = (value == - | borrow != 0 && value == 1 ? 1 :0); 1 | } returnres; }

7.4

#include <iostream.h> classMatrix{ public : Matrix Matrix (constintrows,constintcols) ; (constMatrix&); ~Matrix (void) ; double& operator() (constintrow,constintcol) ; Matrix& operator= (constMatrix&);

fr iend ostream& operator<< (ostream&, Matrix&); fr iend Matrix operator+ (Matr ix&,Matrix&); fr iend Matrix operator(Matr ix&,Matrix&); fr iend Matrix operator* (Matr ix&,Matrix&); int Rows (void) {returnrows;} int Cols (void) {returncols;} protected: classElement { / nonzero element / public : Element (constintrow,constintcol double); , constint Row (void) {returnrow;} constint Col (void) {returncol ;} double& Value (void) {returnvalue;} Element*& Next (void) {returnnext;} Element* CopyList lement *l s ) (E i t; void DeleteLis t (Element *l s ) i t; private: constint row,col; / row and column ofelement / double value; / element value / Element *next; / pointertonext element / }; double& InsertE lem (Element *elem, constintrow,constintcol) ;

int rows,cols; / matrixdimensions / Element *elems; /l / inked- i t elements l s of }; Matrix :E : lement: lement (constintr,constintc,double val) :E :row(r) col(c , )

253

C++ Programming

Copyright 1998 Pragmatix Software

{ value = val; next = 0; } Matrix :E : lement*Matrix :E : lement: :CopyList(Element *l s ) it { Element *prev = 0; Element *f r t 0; i s= Element *copy; for(;l s != 0;l s = l s -Next()) it it it > { copy = new Element(l s >Row(),l s -Col() l s -Value()) it it > ,i t > ; i (prev == 0) f f r t copy; i s= else prev>Next()= copy; prev = copy; } returnf rs ; i t } void Matrix: lement: :E :DeleteLis (Element *l s ) t it { Element *next; for(;l s != 0;l s = next){ it it next = l s -Next() it > ; deletel s ; it } } / InsertE / lem createsa new element and insertsi before t / or afterthe element denoted by elem. / double& Matrix: I tE : nser lem (Element *elem, constintrow,constintcol) { Element* newElem = new Element(row,col 0.0); , i (elem == elems && (elems == 0 | row < elems->Row() | f | | row == elems->Row() && col< elems->Col() ) ){ / insertinfrontofthe l s : / it newElem->Next()= elems; elems = newElem; } else{ / insertafterelem: / newElem->Next()= elem->Next() ; elem->Next()= newElem; } returnnewElem->Value() ; } Matrix :Matr (constintrows,constintcols) : ix {

www.pragsoft.com

Solutions to Exercises

254

Matrix : : rows = rows; Matrix : l = cols; : co s elems = 0; } Matrix :Matr (constMatrix&m) : ix { rows = m.rows; cols= m.cols; elems = m.elems->CopyList (m.elems); } Matrix :~Matr (void) : ix { elems->DeleteList lems); (e } Matrix& Matrix :operator= (constMatrix&m) : { elems->DeleteList lems); (e rows = m.rows; cols= m.cols; elems = m.elems->CopyList (m.elems); return*this ; } double& Matrix: :operator()(constintrow,constintcol) { i (elems == 0 | row < elems->Row() | f | | row == elems->Row() && col< elems->Col() ) / create an element and insertinfront / : returnInsertE lem(elems,row,col) ; / check i i ' the f r t / fts i s element inthe l s : it i (row == elems->Row() && col== elems->Col() f ) returnelems->Value() ; / search the restofthe l s : / it for(Element *elem = elems;elem->Next()!= 0;elem = elem->Next() ) i (row == elem->Next()>Row()){ f i (col== elem->Next()>Col() f ) returnelem->Next()>Value() ; / found i ! / t elsei (col< elem->Next()>Col() f ) break; / doesn'texist / } else i (row < elem->Next()>Row()) f break; / doesn'texist / / createnew element and insertjustafterelem: / returnInsertE lem(elem, row,col) ; } ostream& operator<< (ostream &os,Matrix&m) { Matrix :E : lement *elem = m.elems;

255

C++ Programming

Copyright 1998 Pragmatix Software

for(regis row = 1;row <= m.rows;++row) { ter for(registercol= 1;col<= m.cols;++col) i (elem != 0 && elem->Row() == row && elem->Col()== col){ f os << elem->Value()<< ' t ; \' elem = elem->Next() ; } else os << 0.0 << ' t ; \' os << ' ' \n ; } returnos; } Matrixoperator+ (Matr &p, Matrix&q) ix { Matrixm(p.rows,q.cols) ; / copy p: / for(Matr : lement *pe = p.elems;pe != 0;pe = peix :E >Next() ) m(pe->Row(),pe>Col() = pe) >Value() ; / add q: / for(Matr : lement *qe = q.elems;qe != 0;qe = qeix :E >Next() ) m(qe->Row(),qe>Col() += qe) >Value() ; returnm; } Matrixoperator-(Matr &p, Matrix&q) ix { Matrixm(p.rows,q.cols) ; / copy p: / for(Element *pe = p.elems;pe != 0;pe = pe>Next() ) m(pe->Row(),pe>Col() = pe) >Value() ; / subtractq: / for(Element *qe = q.elems;qe != 0;qe = qe>Next() ) m(qe->Row(),qe>Col() - qe)= >Value() ; returnm; } Matrixoperator* (Matr &p, Matrix&q) ix { Matrixm(p.rows,q.cols) ; for(Element *pe = p.elems;pe != 0;pe = pe>Next() ) for(Element *qe = q.elems;qe != 0;qe = qe>Next() ) i (pef >Col()== qe>Row()) m(pe->Row(),qe>Col() += pe) >Value()* qe>Value() ; returnm; }

7.5

#include <str ing.h> #include <iostream.h> classStr { ing

www.pragsoft.com

Solutions to Exercises

256

public : Str ing Str ing Str ing ~String operator= operator= operator[] Length operator+ operator<< (constchar*) ; (constStr ing&); (constshort) ; (void) ; (constchar*) ; (constStr ing&); (constshort) ; (void) {return( ;} len) (constStr ing&,constStr ing&); (ostream&, Str ing&);

fr iend fr iend

Str ing& Str ing& char& int Str ing ostream&

protected: char short };

*chars; / str characters / ing len; / length ofchars /

Str :St ing(constchar *str ing: r ) { len = str len(st ) r; chars= new char[ + 1]; len strcpy(chars,str) ; } Str :St ing(constStr &str) ing: r ing { len = str l ; . en chars= new char[ + 1]; len strcpy(chars,str .chars) ; } Str :St ing(constshortsize) ing: r { len = size; chars= new char[ + 1]; len chars[0]= ' ' \0 ; } Str :~Str (void) ing: ing { deletechars; } Str ing& Str :operator= (constchar *str ing: ) { short strLen = str len(st ) r; i ( != strLen){ f len deletechars; len = strLen; chars= new char[st rLen+ 1]; } strcpy(chars,str) ; return(*th ) is ; }

257

C++ Programming

Copyright 1998 Pragmatix Software

Str ing& Str :operator= (constStr &str) ing: ing { i (th != &str){ f is i ( != str l { f len . en) deletechars; len = str l ; . en chars= new char[st . en+ 1]; rl } strcpy(chars,str .chars) ; } return(*th ) is ; } char& Str :operator[](constshortindex) ing: { stat char ic dum my = ' ' \0 ; return( index >= 0 && index < len ? chars[ index]:dummy); } Str operator+ (constStr &str1,constStr &str2) ing ing ing { Str result s r1 l + str2. ; ing ( t . en len) strcpy(resul . t chars str1.chars) , ; strcpy(resul . t chars+ str1. str2.chars) len, ; return(resul ) t; } ostream& operator<< (ostream &out,Str &str) ing { out << str .chars; return(out) ; }

7.6

#include <str ing.h> #include <iostream.h> enum Bool{false,true}; typedefunsigned char uchar; classBitVec { public : BitVec (constshortdim); BitVec (constchar*bits) ; BitVec (constBitVec&); ~BitVec (void) { deletevec;} BitVec& operator= (constBitVec&); BitVec& operator&= (constBitVec&); BitVec& operator|= (constBitVec&); BitVec& operator^= (constBitVec&); BitVec& operator<<= (constshort) ; BitVec& operator>>= (constshort) ;

www.pragsoft.com

Solutions to Exercises

258

int operator[] (constshortidx) ; void Set (constshortidx) ; void Reset (constshortidx) ; BitVec operator~ () ; BitVec operator& (constBitVec&); BitVec operator| (constBitVec&); BitVec operator^ (constBitVec&); BitVec operator<< (constshortn); BitVec operator>> (constshortn); Bool operator== (constBitVec&); Bool operator!= (constBitVec&); fr iend ostream& operator<< (ostream&, BitVec&);

protected: uchar short };

*vec; bytes;

/ vectorof8*bytes bits / / bytes inthe vector /

/ setthe bitdenoted by idxto1 / in inevoid BitVec: l :Set(constshortidx) { vec[idx/8]|= (1 << idx%8); } / resetthe bitdenoted by idxto0 / in inevoid BitVec: l :Reset(constshortidx) { vec[idx/8]&= ~(1 << idx%8); } in ineBitVec& BitVec: l :operator&= (constBitVec &v) { return(*this = (*th ) v; ) is & } in ineBitVec& BitVec: l :operator|= (constBitVec &v) { return(*this = (*th ) v; ) is | } in ineBitVec& BitVec: l :operator^= (constBitVec &v) { return(*this = (*th ) v; ) is ^ } in ineBitVec& BitVec: l :operator<<= (constshortn) { return(*this = (*th ) ) is << n; } in ineBitVec& BitVec: l :operator>>= (constshortn)

259

C++ Programming

Copyright 1998 Pragmatix Software

{ return(*this = (*th ) ) is >> n; } / returnthe bitdenoted by idx / in ineintBitVec: l :operator[](constshortidx) { returnvec[idx/8]& (1 << idx%8) ? true :false; } in ineBoolBitVec: l :operator!= (constBitVec &v) { return*this== v ? false:true; } BitVec: i :B tVec(constshortdim) { bytes = dim /8 + (dim % 8 == 0 ? 0 :1); vec = new uchar[bytes] ; for(regis i= 0;i< bytes;++i) ter vec[i = 0; ] } BitVec: i :B tVec(constchar *bits ) { intlen = str len(bi ) ts ; bytes = len /8 + ( % 8 == 0 ? 0 :1); len vec = new uchar[bytes] ; for(regis i= 0;i< bytes;++i) ter vec[i = 0; ]

/ al bitsare ini i l y / l t a l zero

/ in t a i al bitstozero / i i l ze l

for( = len -1;i>= 0;-i i -) i (*bi f ts++ == '1 ) ' / setthe 1 bits / vec[i ] (1 << ( /8 |= i%8)) ; } BitVec: i :B tVec(constBitVec &v) { bytes = v.bytes; vec = new uchar[bytes] ; for(regis i= 0;i< bytes;++i) / copy bytes ter / vec[i = v.vec[ ] ] i; } BitVec& BitVec: :operator= (constBitVec& v) { for(regis i= 0;i< (v.bytes< bytes ? v.bytes:bytes) ++i) ter ; vec[i = v.vec[ ] ] i; / copy bytes / for(;i< bytes;++i) / extrabytes in*this / vec[i = 0; ] return*this ; }

www.pragsoft.com

Solutions to Exercises

260

/ bitwiseCOMPLEMENT / BitVec BitVec: :operator~ (void) { BitVec r(bytes* 8); for(regis i= 0;i< bytes;++i) ter r.vec[ ] ~vec[i ; i= ] returnr; } / bitwiseAND / BitVec BitVec: :operator& (constBitVec &v) { BitVec r( (bytes> v.bytes? bytes :v.bytes)* 8); for(regis i= 0;i< (bytes< v.bytes? bytes :v.bytes) ++i) ter ; r.vec[ ] vec[i & v.vec[ ] i= ] i; returnr; } / bitwiseOR / BitVec BitVec: :operator|(constBitVec &v) { BitVec r( (bytes> v.bytes? bytes :v.bytes)* 8); for(regis i= 0;i< (bytes< v.bytes? bytes :v.bytes) ++i) ter ; r.vec[ ] vec[i |v.vec[ ] i= ] i; returnr; } / bitwiseexclusive/ OR BitVec BitVec: :operator^ (constBitVec &v) { BitVec r( (bytes> v.bytes? bytes :v.bytes)* 8); for(regis i= 0;i< (bytes< v.bytes? bytes :v.bytes) ++i) ter ; r.vec[ ] vec[i ^ v.vec[ ] i= ] i; returnr; } / SHIFT LEFT by n bits / BitVec BitVec: :operator<< (constshortn) { BitVec r(bytes* 8); int zeros = n /8; / bytes on the lef tobecome zero / t int shif = n % 8; / lef shif forremaining bytes t / t t registeri ; for( = bytes -1;i>= zeros;-i / shif bytes lef i -) / t t r.vec[ ] vec[i-zeros] i= ; for(;i>= 0;-i -) r.vec[ ] 0; i= unsigned char prev = 0; / zero lef bytes / t

for( = zeros;i< r.bytes;++i){ i / shif bitslef / t t r.vec[ ] (r i = .vec[ ] shif ) prev; i<< t|

261

C++ Programming

Copyright 1998 Pragmatix Software

prev = vec[i-zeros]>> (8 -shif ) t; } returnr; } / SHIFT RIGHT by n bits / BitVec BitVec: :operator>> (constshortn) { BitVec r(bytes* 8); int zeros = n /8; / bytes on the righttobecome zero / int shif = n % 8; t /r / ightshif forremaining bytes t registeri ; for( = 0;i< bytes -zeros;++i) i r.vec[ ] vec[i+ zeros] i= ; for(;i< bytes;++i) r.vec[ ] 0; i= / shif bytes r / t ight / zero r / ightbytes

uchar prev = 0; for( = r.bytes-zeros-1;i>= 0;-i { / shif bitsr i -) / t ight r.vec[ ] (r i = .vec[ ] shif ) prev; i>> t| prev = vec[i+ zeros]<< (8 -shif ) t; } returnr; } BoolBitVec: :operator== (constBitVec &v) { int smaller= bytes < v.bytes? bytes :v.bytes; registeri ; for( = 0;i< smaller ++i) i ; / compare bytes / i (vec[ ] v.vec[ ] f i != i) returnfalse; for( = smaller i< bytes;++i) / extrabytes inf rs operand i ; / i t i (vec[ ] 0) f i != returnfalse; for( = smaller i< v.bytes;++i) / extrabytes insecond operand i ; / i (v.vec[ ] 0) f i != returnfalse; returntrue; } ostream& operator<< (ostream &os,BitVec &v) { constintmaxBytes = 256; char buf[maxBytes * 8 + 1]; char *str= buf; int n = v.bytes> maxBytes ? maxBytes :v.bytes; for(regis i= n- i>= 0;-i ter 1; -) for(registerj= 7;j>= 0;-j -) *str++ = v.vec[ ] (1 << j ? '1' '0 ; i& ) : ' *str= ' ' \0 ;

www.pragsoft.com

Solutions to Exercises

262

os << buf; returnos; }

8.1

#include "bitvec.h" enum Month { Jan,Feb,Mar,Apr,May, Jun,JulAug, Sep,Oct,Nov,Dec , }; in ineBoolLeapYear(constshortyear) {returnyear%4 == 0;} l classYear :publicBitVec { public : Year(constshortyear) ; voidWorkDay (constshortday); / setday as work day / voidOffDay (constshortday); / setday as offday / BoolWorking (constshortday); / true i a work day / f short Day (constshortday, / convertdate today / constMonth month,constshortyear); protected: short year; / calendaryear / }; Year: :Year(constshortyear):BitVec(366) { Year: :year= year; } void Year: :WorkDay (constshortday) { Set(day); } void Year: fDay (constshortday) :Of { Reset(day); } BoolYear: :Working (constshortday) { return(*this [day]== 1 ? true :false; ) } shortYear: :Day (constshortday,constMonth month,constshortyear) { stat shortdays[12]= { ic 31,28,31,30,31,30,31,31,20,31,30,31 }; days[Feb]= LeapYear(year)? 29 :28; intres= day; for(regis i= Jan;i< month;++i) ter

263

C++ Programming

Copyright 1998 Pragmatix Software

res+= days[i ; ] returnres; }

8.2

#include <stdl .h> ib #include <time.h> #include "matrix .h" in inedouble Abs(double n) {returnn >= 0 ? n :l n;} classLinEqns :publicMatrix{ public : LinEqns (constintn,double *soln) ; voidGenerate(constintcoef) ; voidSolve (void) ; private: Matrix solut ion; }; LinEqns::L inEqns (constintn,double*soln) :Matrix(n n+1),solut , ion(n,1) { for(regis r= 1;r<= n;++r) ter solut ion(r 1) = soln[r-1]; , } void LinEqns::Generate(constintcoef) { intmid = coef/2; srand((unsigned int) ime(0)) t ; / setrandom seed /

for(regis r= 1;r<= Rows();++r) { ter (*this ( , ) rCols() = 0.0; / ini i l z righthand side ) / t ai e / generate equationswhose coeff ients / ic / do not exceed coef: / for(registerc = 1;c < Cols( ; ) ++c) { (*th ) rc)= (double)(mid -random(1000) % coef) is ( , ; (*th ) rCols( ) (*th ) rc)* solut is ( , ) += is ( , ion(c 1); , } } } / solve equationsusing Gaussian el / iminat ion void LinEqns::Solve(void) { double constepsi = 1e- / lmostzero'quanti lon 5;/ 'a ty double temp; intdiag,piv,r,c;

www.pragsoft.com

Solutions to Exercises

264

for(diag = 1;diag <= Rows();++diag) { / diagonal / piv= diag; / pivot / for(r= diag + 1;r<= Rows();++r) / upper tr / iangle i (Abs((* is (p , f th ) iv diag))< Abs((*th ) rdiag)) is ( , ) piv= r; / choose new pivot / / make sure there isa unique solut / ion: i (Abs((* is (p , f th ) iv diag))< epsi lon){ i (Abs((* is (d , f th ) iag Cols() ) epsi )< lon) cout<< "inf i solut in te ions\n" ; else cout<< "no solut ion\n" ; return; } i (piv!= diag){ f / swap pivi with diagonal: / t for(c= 1;c <= Cols( ; ) ++c) { temp = (*th ) iag, is (d c); (*this (d c)= (*this (p , ) iag, ) iv c); (*this (p , = temp; ) iv c) } } / normalisediag row so thatm[diag,diag]= 1: / temp = (*th ) iag, is (d diag); (*this (d diag)= 1.0; ) iag, for(c= diag + 1;c <= Cols( ; ) ++c) (*th ) iag, = (*th ) iag, /temp; is (d c) is (d c) / now el / iminateentr below the pivot: ies for(r= diag + 1;r<= Rows();++r) { double factor= (*th ) rdiag); is ( , (*th ) rdiag)= 0.0; is ( , for(c= diag + 1;c <= Cols() ++c) ; (*this ( , - (*this (d c)* factor ) rc) = ) iag, ; } / displayel / iminat step: ion cout<< "el iminated below pivotincolumn "<< diag << ' ' \n ; cout<< *this ; } / back substi te / tu : Matrixsoln(Rows() 1); , soln(Rows() 1) = (*th ) , is (Rows() Cols( ) , );

/ the lastunknown /

for(r= Rows()-1;r>= 1;-r){ / the rest / double sum = 0.0; for(diag = r+ 1;diag <= Rows();++diag) sum += (*th ) rdiag)* soln(diag,1); is ( , soln(r 1) = (*th ) rCols( ) sum; , is ( , )} cout << "solut \n" ion: ; cout << soln; }

265

C++ Programming

Copyright 1998 Pragmatix Software

8.3

#include "bitvec.h" classEnumSet :publicBitVec { public : EnumSet (constshortmaxCard) :BitVec(maxCard){} EnumSet (BitVec& v):BitVec(v) {*this= (EnumSet&)v;} fr iend EnumSet operator+ (EnumSet &s,EnumSet &t); fr iend EnumSet operator- (EnumSet &s,EnumSet &t); fr iend EnumSet operator* (EnumSet &s,EnumSet &t); fr iend Bool operator% (constshortelem, EnumSet &s); fr iend Bool operator<= (EnumSet &s,EnumSet &t); fr iend Bool operator>= (EnumSet &s,EnumSet &t); fr iend EnumSet& operator<< (EnumSet &s,constshortelem); fr iend EnumSet& operator>> (EnumSet &s,constshortelem); }; in ineEnumSet operator+ (EnumSet &s,EnumSet &t) l { returns |t; } / union /

in ineEnumSet operator-(EnumSet &s,EnumSet &t)/ dif l / ference { returns & ~t; } in ineEnumSet operator* (EnumSet &s,EnumSet &t) l { returns & t; } in ineBooloperator% (constshortelem, EnumSet &t) l { returnt[e lem]; } in ineBooloperator<= (EnumSet &s,EnumSet &t) l { return(t& s)== s; } in ineBooloperator>= (EnumSet &s,EnumSet &t) l { return(t& s)== t; } EnumSet& operator<< (EnumSet &s,constshortelem) { s.Set(e lem); returns; } EnumSet& operator>> (EnumSet &s,constshortelem) / intersect / ion

www.pragsoft.com

Solutions to Exercises

266

{ s.Reset(e lem); returns; }

8.4

typedefint Key; typedef double Data; enum Bool{ false, true }; classDatabase { public : vir tual voidInsert vir tual voidDelete vir tual BoolSearch };

(Key key,Data data) {} (Key key) {} (Key key,Data &data) {returnfalse;}

A B-tree consists of a set of nodes, where each node may contain up to 2n records and have 2n+1 children. The number n is called the order of the tree. Every node in the tree (except for the root node) must have at least n records. This ensures that at least 50% of the storage capacity is utilized. Furthermore, a nonleaf node that contains m records must have exactly m+1 children. The most important property of a B-tree is that the insert and delete operations are designed so that the tree remains balanced at all times.
#include <iostream.h> #include "database.h" constintmaxOrder = 256; / max treeorder /

classBTree :publicDatabase { public : classPage; classI tem { / representseach stored i / tem public : I tem (void) {right= 0;} I tem (Key,Data); Key& KeyOf (void) {returnkey;} Data& DataOf (void) {returndata;} Page*& Subtree (void) {returnright ;} fr iend ostream& operator<< (ostream&, I tem&); private: Key key;/ i / tem'skey Data data; /i / tem'sdata Page *r ight / pointertor ; / ightsubtree }; classPage { public : ~Page / representseach treenode / Page (void) (constintsize) ; {deletei tems;}

267

C++ Programming

Copyright 1998 Pragmatix Software

Page*& Left (constintofI tem); Page*& Right (constintofI tem); constint Size (void) {returnsize;} int& Used (void) {returnused;} I tem& operator[] (constintn) {returni tems[n];} Bool BinarySearch(Key key,int&idx); int CopyItems (Page *dest,constintsrcIdx, constintdestIdx,constintcount) ; Bool Insert tem I ( tem &item, intatIdx) I ; Bool DeleteI tem ( atIdx) int ; void PrintPage(ostream& os,constintmargin); private: constint size;/ max no.ofi / tems per page int used; / no.ofi / tems on the page Page *lef ;/ t/ pointertothe lef - ost subtree tm I tem *i tems; / the i / tems on the page }; public : BTree (constintorder) ; ~BTree (void) {FreePages(root) ;} vir tual voidInsert (Key key,Data data); vir tual voidDelete (Key key); vir tual BoolSearch (Key key,Data &data); fr iend ostream& operator<< (ostream&, BTree&); protected: constintorder; Page *root; Page *bufP;

/ orderoftree / / rootofthe tree / / bufferpage fordistr ion/merging / ibut

vir void FreePages tual (Page *page); vir I tual tem* SearchAux (Page *tree,Key key); vir I tual tem* InsertAux( tem *item,Page *page); I vir void tual vir void tual vir void tual }; BTree:: tem:: tem (Key k,Data d) I I { key = k; data = d; right= 0; } ostream& operator<< (ostream& os,BTree:: tem &item) I { os << i tem.key << ''<< i tem.data; returnos; } DeleteAux1 DeleteAux2 Underf low (Key key,Page *page,Bool&underf low); (Page *parent,Page *page, constintidx,Bool&underf low); (Page *page,Page *chi , ld intidx,Bool&underflow);

www.pragsoft.com

Solutions to Exercises

268

BTree::Page::Page (constintsz):size(sz) { used = 0; lef = 0; t i tems = new I tem[size] ; } / returnthe lef subtree ofan i / t tem BTree::Page*& BTree::Page::Lef (constintofI t tem) { returnofI tem <= 0 ? lef : tems[of tem -1].Subtree() ti I ; } / returnthe r / ightsubtree ofan i tem BTree::Page*& BTree::Page::Right(constintofI tem) { returnofI tem < 0 ? lef :i t tems[of tem].Subtree() I ; } / do a binary search on i / tems ofa page / returnstrue i successfuland falseotherwise / f BoolBTree::Page::BinarySearch (Key key,int&idx) { int = 0; low int high = used -1; int mid; do { mid = ( + high)/2; low i (key <= i f tems[mid].KeyOf() ) high = mid -1; / restr c tolower half / it i (key >= i f tems[mid].KeyOf() ) low = mid + 1; / restr c toupper half / it } while( <= high); low Boolfound = low -high > 1; idx= found ? mid :high; returnfound; } / copy a setofi / tems from page topage intBTree::Page::CopyItems (Page *dest, constintsrcIdx, constintdestIdx,constintcount) { for(registeri= 0;i< count;++i) / straightcopy / dest>items[destIdx+ i = i ] tems[src + i ; Idx ] returncount; }

269

C++ Programming

Copyright 1998 Pragmatix Software

/ insertan i / tem intoa page BoolBTree::Page:: Inser I em ( tem &item, intatIdx) tt I { for(registeri= used;i> atIdx;-i / shif r -) / t ight i tems[i = i ] tems[i-1]; i tems[at Idx]= i tem; / insert / return++used >= size; / overf / low? } / deletean i / tem from a page BoolBTree::Page::Delete tem ( atIdx) I int { for(registeri= atIdx;i< used -1;++i) i tems[i = i ] tems[i+ 1]; return-used < size/2; } / recurs / ivelyprinta page and i subtrees ts void BTree::Page::Pr tPage (ostream& os,constintmargin) in { char margBuf[128]; / buildthe margin str / ing: for( i= 0;i<= margin;++i) int margBuf[i = '' ] ; margBuf[ ] ' ' i = \0 ; / printthe lef - ost chi : / tm ld i (Left != 0) f (0) Left(0)>PrintPage(os,margin + 8); / printpage and remaining chi / ldren: for( = 0;i< used;++i){ i os << margBuf; os << (*th ) i << ' ' is [ ] \n ; i (Right( ) 0) f i!= Right( ) PrintPage(os,margin + 8); i> } } BTree::BTree (constintord):order(ord) { root= 0; bufP = new Page(2 * order+ 2); } void BTree:: Inser (Key key,Data data) t { I tem i tem(key,data), *receive;

/ shif lef / t t / underf / low?

www.pragsoft.com

Solutions to Exercises

270

i (root== 0) { f / empty tree / root= new Page(2 * order) ; root>Insert tem(i I tem,0); } elsei ((receive= InsertAux(&item,root) != 0) { f ) Page *page = new Page(2 * order) ; / new root / page->Insert tem(*receive,0); I page->Left(0)= root; root= page; } } void BTree::Delete(Key key) { Boolunderf low; DeleteAux1(key,root, underf low); i (underf && rootf low >Used()== 0) { / dispose root / Page *temp = root; root= root>Left(0) ; deletetemp; } } BoolBTree::Search (Key key,Data &data) { I tem *i tem = SearchAux(root, key); i ( tem == 0) fi returnfalse; data = i tem->DataOf() ; returntrue; } ostream& operator<< (ostream& os,BTree &tree) { i (tree. f root!= 0) tree. root>PrintPage(os,0); returnos; } / recurs / ivelyfreea page and i subtrees ts void BTree::FreePages (Page *page) { i (page != 0) { f FreePages(page>Left(0) ; ) for(registeri= 0;i< page->Used();++i) FreePages(page>Right( ) ; i) deletepage; } } / recurs / ivelysearch the treeforan i tem with matching key

271

C++ Programming

Copyright 1998 Pragmatix Software

BTree:: tem* BTree::SearchAux (Page *tree,Key key) I { int idx; I tem *i tem; i (tree== 0) f return0; i (treef >BinarySearch(key,idx)) return&((*tree) idx] ; [ ) returnSearchAux(idx< 0 ? tree>Left(0) :tree>Right( , idx) key); } / insertan i / tem intoa page and spl t page i i overf i the ft lows BTree:: tem* BTree:: I Inser tAux ( tem *i I tem,Page *page) { Page *chi ; ld int idx; i (pagef >BinarySearch( temi >KeyOf() idx)) , return0; / already intree / i ((chi = page->Right( ) 0) f ld idx) != i tem = InsertAux( tem,chi ; i ld)

/ chi isnot a leaf / ld

i ( tem != 0) { fi / page isa leaf or passed up / , i (pagef >Used()< 2 * order){ / insertinthe page / page->Insert tem(*i I tem,idx+ 1); } else { / page isful , i / lspl t Page *newP = new Page(2 * order) ; bufP>Used()= page->CopyItems(bufP,0,0,page->Used()) ; bufP>Insert tem(*i I tem,idx+ 1); intsize= bufP>Used(); inthalf= size/2; page->Used()= bufP>CopyItems(page,0,0,half ; ) newP->Used()= bufP>CopyItems(newP, half+ 1,0,size-half-1); newP->Left(0)= bufP>Right(hal ) f; *item = (*bufP)[hal ] f; i tem->Subtree()= newP; returni tem; } } return0; } / deletean i / tem from a page and dealwith underf lows void BTree::DeleteAux1 (Key key,Page *page,Bool&underf low) { / the mid i / tem

www.pragsoft.com

Solutions to Exercises

272

int idx; Page *chi ; ld underf = false; low i (page == 0) f return; i (pagef >BinarySearch(key,idx)){ i ((chi = page->Left( ) f ld idx) == 0) { / page isa leaf / underf = page->DeleteI low tem(idx) ; } else { / page isa subtree / / deletefrom subtree: / DeleteAux2(page,chi , ld idx,underf low); i (underf f low) Underflow(page,chi , -1,underf ld idx low); } } else{ / isnot on thispage / chi = page->Right( ; ld idx) DeleteAux1(key,chi , ld underf low); / should be inchi / ld i (underf f low) Underf low(page,chi , ld idx,underf low); } } / deletean i / tem and dealwith underf lows by borrowing /i / tems from neighboring pages or merging two pages void BTree::DeleteAux2 (Page *parent,Page *page, constintidx,Bool&underf low) { Page *chi = page->Right(pageld >Used()-1); i (chi != 0) { f ld / page isnot a leaf / DeleteAux2(parent,chi , ld idx,underf low);/ go anotherleveldown / i (underf f low) Underf low(page,chi , ld page->Used()-1,underf low); } else{ / page isa leaf / / save right / : Page *r ight= parent>Right( ; idx) / borrow an i / tem from page forparent: page->CopyItems(parent,page->Used()-1,idx,1); / restoreright / : parent>Right( idx)= right ; underf = page->DeleteI low tem(page>Used()-1); } } / handle underf / lows void BTree::Underf (Page *page,Page *chi , low ld intidx,Bool&underf low) { Page *lef = idx< page->Used()-1 ? chi :page->Left( ; t ld idx) Page *r ight= lef == chi ? page->Right(++idx):chi ; t ld ld

273

C++ Programming

Copyright 1998 Pragmatix Software

/ copy contentsoflef , / tparenti tem,and rightonto bufP: intsize= lef - CopyItems(bufP,0,0,lef - Used()) t > t > ; (*bufP) i ] (*page)[ ; [s ze = idx] bufP>Right(s ize++) = right>Left(0) ; size+= right>CopyItems(bufP,0,size,right>Used()) ; i (s > 2 * order){ f ize / distr / ibutebufP i tems between lef and right t : inthalf= size/2; lef - Used()= bufPt> >CopyItems(lef , 0,half ; t0, ) r ight>Used()= bufP>CopyItems(r ight half+ 1,0,size-half-1); , r ight>Left(0)= bufP>Right(hal ) f; (*page)[ idx]= (*bufP)[hal ] f; page->Right( idx)= r ight ; underf = false; low } else{ / merge,and freethe r / ightpage: lef - Used()= bufPt> >CopyItems(lef , 0,size) t0, ; underf = page->DeleteI low tem(idx) ; deleter ight ; } }

A B*-tree is a B-tree in which most nodes are at least 2/3 full (instead of 1/2 full). Instead of splitting a node as soon as it becomes full, an attempt is made to evenly distribute the contents of the node and its neighbor(s) between them. A node is split only when one or both of its neighbors are full too. A B*-tree facilitates more economic utilization of the available store, since it ensures that at least 66% of the storage occupied by the tree is actually used. As a result, the height of the tree is smaller, which in turn improves the search speed. The search and delete operations are exactly as in a B-tree; only the insertion operation is different.
classBStar:publicBTree { public : BStar (constintorder):BTree(order){} vir tual voidInsert (Key key,Data data); protected: vir I tual tem* InsertAux( tem *item,Page *page); I vir I tual tem* Overf low ( tem *item,Page *page, I Page *chi , idx) ld int ; }; / insertwith overf / low/underf handling low void BStar: Inser (Key key,Data data) : t {

www.pragsoft.com

Solutions to Exercises

274

I tem i tem(key,data); I tem *overf low; Page *lef , ight t*r ; Booldummy; i (root== 0) { f / empty tree / root= new Page(2 * order) ; root>Insert tem(i I tem,0); } elsei ((overf = InsertAux(&item,root) != 0) { f low ) lef = root; t / rootbecomes a lef chi / t ld root= new Page(2 * order) ; r ight= new Page (2 * order) ; root>Insert tem(*overf I low,0); root>Left(0)= lef ; t / the lef - ost chi ofroot / tm ld root>Right(0)= r ight / the rightchi ofroot ; / ld r ight>Left(0)= overf >Subtree() low; /r / ightisunderf lown (s == 0): ize Underflow(root r , ight 0,dum my); , } } / insertsand dealswith overf / lows I tem* BStar: Inser : tAux ( tem *i I tem,Page *page) { Page *chi ; ld int idx; i (pagef >BinarySearch( temi >KeyOf() idx)) , return0; / already intree / i ((chi = page->Right( ) 0) { f ld idx) != / chi not a leaf / ld : i (( tem = InsertAux( tem,chi ) 0) f i i ld) != returnOverflow( tem,page,chi , i ld idx) ; } elsei (pagef >Used()< 2 * order){ / i / tem f t innode is page->Insert tem(*i I tem,idx+ 1); } else{ / node isful / l intsize= page->Used(); bufP>Used()= page->CopyItems(bufP,0,0,size) ; bufP>Insert tem(*i I tem,idx+ 1); bufP>CopyItems(page,0,0,size) ; *i tem = (*bufP)[s ze ; i ] returni tem; } return0; } / handles underf / lows I tem* BStar: :Overf ( tem *item,Page *page, low I Page *chi , idx) ld int { Page *lef = idx< page->Used()-1 ? chi :page->Left( ; t ld idx) Page *r ight= lef == chi ? page->Right(++idx):chi ; t ld ld

275

C++ Programming

Copyright 1998 Pragmatix Software

/ copy lef , / toverf lown and parenti tems,and rightintobuf: bufP>Used()= lef - CopyItems(bufP,0,0,lef - Used()) t> t> ; i (chi == lef ){ f ld t bufP>Insert tem(*i I tem,bufP>Used()) ; bufP>Insert tem((*page)[ , I idx] bufP>Used()) ; bufP>Right(bufP>Used()-1) = right>Left(0) ; bufP>Used()+= r ight>CopyItems(bufP,0,bufP>Used(),r ight>Used()) ; } else{ bufP>Insert tem((*page)[ , I idx] bufP>Used()) ; bufP>Right(bufP>Used()-1) = right>Left(0) ; bufP>Used()+= r ight>CopyItems(bufP,0,bufP>Used(),r ight>Used()) ; bufP>Insert tem(*i I tem,bufP>Used()) ; } i (bufPf >Used()< 4 * order+ 2) { / distr / ibutebuf between lef and right t : intsize= bufP>Used(),half ; lef - Used()= bufPt> >CopyItems(lef , 0,half= size/2) t0, ; r ight>Used()= bufP>CopyItems(r ight half+ 1,0,size-half-1); , r ight>Left(0)= bufP>Right(hal ) f; (*page)[ idx]= (*bufP)[hal ] f; page->Right( idx)= r ight ; return0; } else{ / spl t 3 pages: / i int Page *newP = new Page(2 * order) ; int mid1,mid2; mid1 = lef - Used()= bufPt> >CopyItems(lef , 0,(4 * order+ 1) /3); t0, mid2 = right>Used()= bufP>CopyItems(r ight mid1 + 1,0,4 * order/3); , mid2 += mid1 + 1; newP->Used()= bufP>CopyItems(newP, mid2 + 1,0,(4 * order+ 2) /3); r ight>Left(0)= bufP>Right(mid1); bufP>Right(mid1)= r ight ; newP->Left(0)= bufP>Right(mid2); bufP>Right(mid2)= newP; (*page)[ idx]= (*bufP)[mid2]; i (pagef >Used()< 2 * order){ page->Insert tem((*bufP) I [mid1], idx) ; return0; } else { *item = (*page)[page>Used()-1]; (*page)[page>Used()-1] = (*bufP) [mid1]; returni tem; } } }

9.1

template<class Type> void Swap (Type &x, Type &y)

www.pragsoft.com

Solutions to Exercises

276

{ Type tmp = x; x = y; y = tmp; }

9.2

#include <str ing.h> enum Bool{false,true}; template <class Type> void BubbleSort(Type *names, constintsize) { Boolswapped; do { swapped = false; for(registeri= 0;i< size-1;++i){ i (names[i > names[i+1]){ f ] Type temp = names[i] ; names[i]= names[i+1]; names[i+1]= temp; swapped = true; } } } while(swapped); } / special za ion: / i t void BubbleSort(char**names, constintsize) { Boolswapped; do { swapped = false; for(registeri= 0;i< size-1;++i){ i (strcmp(names[i] names[i+1])> 0 ){ f , char *temp = names[i] ; names[i]= names[i+1]; names[i+1]= temp; swapped = true; } } } while(swapped); }

9.3

#include <str ing.h> #include <iostream.h> enum Bool{false, rue}; t typedefchar *Str ;

277

C++ Programming

Copyright 1998 Pragmatix Software

template <class Type> classBinNode { public : BinNode (constType&); ~BinNode (void) {} Type& Value (void) {returnvalue;} BinNode*& Left (void) {returnlef ;} t BinNode*& Right (void) {returnr ight ;} void FreeSubtree (BinNode *subtree); void InsertNode (BinNode *node,BinNode *&subtree); void DeleteNode (constType&, BinNode *&subtree); constBinNode* FindNode (constType&, constBinNode *subtree); void PrintNode (constBinNode *node); private: Type value; BinNode *lef ; t BinNode *r ight ; };

/ node value / / pointertolef chi / t ld / pointertorightchi / ld

template <class Type> classBinTree { public : BinTree (void) ; ~BinTree(void) ; voidInsert (constType &val) ; void Delete (constType &val) ; BoolFind (constType &val) ; voidPrint (void) ; protected: BinNode<Type> *root;/ rootnode ofthe tree / }; template <class Type> BinNode<Type>::BinNode (constType &val) { value = val; lef = r t ight= 0; } / special za ion: / i t BinNode<Str>::BinNode (constStr&str) { value = new char[st l t ) 1]; r en(s r + strcpy(value,str) ; lef = r t ight= 0; } template <class Type> void BinNode<Type>::FreeSubtree (BinNode<Type> *node)

www.pragsoft.com

Solutions to Exercises

278

{ i (node != 0) { f FreeSubtree(node>left ; ) FreeSubtree(node>right) ; deletenode; } } template <class Type> void BinNode<Type>::InsertNode (BinNode<Type> *node,BinNode<Type> *&subtree) { i (subtree == 0) f subtree = node; elsei (nodef >value <= subtree>value) InsertNode(node,subtree>left ; ) else InsertNode(node,subtree>right) ; } / special za ion: / i t void BinNode<Str>:: InsertNode (BinNode<Str> *node,BinNode<Str> *&subtree) { i (subtree == 0) f subtree = node; elsei (strcmp(nodef >value,subtree>value)<= 0) InsertNode(node,subtree>left ; ) else InsertNode(node,subtree>right) ; } template <class Type> void BinNode<Type>::DeleteNode (constType &val,BinNode<Type> *&subtree) { intcmp; i (subtree == 0) f return; i (val< subtreef >value) DeleteNode(val subtree, >left) ; elsei (val> subtreef >value) DeleteNode(val subtree, >right) ; else{ BinNode* handy = subtree; i (subtreef >left== 0) / no lef subtree / t subtree = subtree>right; else i (subtreef >right== 0) / no r / ightsubtree subtree = subtree>left ; else { / lef and rightsubtree / t subtree = subtree>right; / insertlef subtree intorightsubtree: / t InsertNode(subtree>left subtree, >right) ; }

279

C++ Programming

Copyright 1998 Pragmatix Software

deletehandy; } } / special za ion: / i t void BinNode<Str>::DeleteNode (constStr&str, BinNode<Str> *&subtree) { intcmp; i (subtree == 0) f return; i ((cmp = strcmp(str subtreef , >value))< 0) DeleteNode(str subtree, >left) ; elsei (cmp > 0) f DeleteNode(str subtree, >right) ; else{ BinNode<Str>* handy = subtree; i (subtreef >left== 0) / no lef subtree / t subtree = subtree>right; else i (subtreef >right== 0) / no r / ightsubtree subtree = subtree>left ; else { / lef and rightsubtree / t subtree = subtree>right; / insertlef subtree intorightsubtree: / t InsertNode(subtree>left subtree, >right) ; } deletehandy; } } template <class Type> constBinNode<Type>* BinNode<Type>::FindNode (constType &val,constBinNode<Type> *subtree) { i (subtree == 0) f return0; i (val< subtreef >value) returnFindNode(val subtree, >left ; ) i (val> subtreef >value) returnFindNode(val subtree, >right) ; returnsubtree; } / special za ion: / i t constBinNode<Str>* BinNode<Str>::F indNode (constStr&str, constBinNode<Str> *subtree) { intcmp; return(subtree == 0) ?0 :((cmp = strcmp(str subtree, >value))< 0

www.pragsoft.com

Solutions to Exercises

280

? FindNode(str subtree, >left ) :(cmp > 0 ? FindNode(str subtree, >right) :subtree)) ; } template <class Type> void BinNode<Type>::Pr intNode (constBinNode<Type> *node) { i (node != 0) { f PrintNode(node>left ; ) cout<< node->value << '' ; PrintNode(node>right) ; } } template <class Type> void BinTree<Type>:: Insert(constType &val) { root>InsertNode(new BinNode<Type>(val) root) , ; } template <class Type> BinTree<Type>::BinTree (void) { root= 0; } template <class Type> BinTree<Type>::~BinTree(void) { root>FreeSubtree(root) ; } template <class Type> void BinTree<Type>::Delete(constType &val) { root>DeleteNode(val root) , ; } template <class Type> BoolBinTree<Type>::Find(constType &val) { returnroot>FindNode(val root)!= 0; , } template <class Type> void BinTree<Type>::Pr (void) int { root>PrintNode(root) cout<< ' ' ; \n ; }

281

C++ Programming

Copyright 1998 Pragmatix Software

9.4

#include <iostream.h> enum Bool{ false, true }; template <class Key,classData> classDatabase { public : vir tual voidInsert (Key key,Data data) {} vir tual voidDelete (Key key) {} vir tual BoolSearch (Key key,Data &data) {returnfalse;} }; template <class Key,classData> classPage; template <class Key,classData> classI tem { / representseach stored i / tem public : I tem (void) {right= 0;} I tem (Key,Data); Key& KeyOf (void) {returnkey;} Data& DataOf (void) {returndata;} Page<Key, Data>*& Subtree (void) {returnr ight ;} fr iend ostream& operator<< (ostream&, I tem&); private: Key key;/ i / tem'skey Data data; /i / tem'sdata Page<Key, Data> *r ight / pointertor ; / ightsubtree }; template <class Key,classData> classPage { / representseach treenode / public : Page (constintsize) ; ~Page (void) {deletei tems;} Page*& Left (constintofI tem); Page*& Right (constintofI tem); constint Size (void) {returnsize;} int& Used (void) {returnused;} I tem<Key, Data>& operator[] (constintn) {returni tems[n];} Bool BinarySearch(Key key,int&idx); int CopyItems (Page *dest,constintsrcIdx, constintdestIdx,constintcount) ; Bool Insert tem I ( tem<Key, Data> &item, intatIdx) I ; Bool DeleteI tem ( atIdx) int ; void PrintPage(ostream& os,constintmargin); private: constint size; / / max no.ofi tems per page int used; / no.ofi / tems on the page Page *lef ;/ t/ pointertothe lef - ost subtree tm I tem<Key, Data> *items; / the i / tems on the page }; template <class Key,classData>

www.pragsoft.com

Solutions to Exercises

282

classBTree :publicDatabase<Key, Data> { public : BTree (constintorder) ; ~BTree (void) {FreePages(root) ;} vir tual voidInsert (Key key,Data data); vir tual voidDelete (Key key); vir tual BoolSearch (Key key,Data &data); fr iend ostream& operator<< (ostream&, BTree&); protected: constintorder; / orderoftree / Page<Key, Data> *root; / rootofthe tree / Page<Key, Data> *bufP; / bufferpage fordistr ion/merging / ibut vir void FreePages tual vir I tual tem<Key, Data>* vir I tual tem<Key, Data>* (Page<Key, Data> *page); SearchAux (Page<Key, Data> *tree,Key key); InsertAux( tem<Key, Data> *i I tem, Page<Key, Data> *page); (Key key,Page<Key, Data> *page, Bool&underflow); (Page<Key, Data> *parent, Page<Key, Data> *page, constintidx,Bool&underf low); (Page<Key, Data> *page, Page<Key, Data> *chi , ld intidx,Bool&underflow);

vir void tual vir void tual

DeleteAux1 DeleteAux2

vir void tual

Underf low

}; template <class Key,classData> I tem<Key, Data>:: tem (Key k,Data d) I { key = k; data = d; right= 0; } template <class Key,classData> ostream& operator<< (ostream& os,I tem<Key,Data> &item) { os << i tem.key << ''<< i tem.data; returnos; } template <class Key,classData> Page<Key, Data>::Page (constintsz):size(sz) { used = 0; lef = 0; t i tems = new I tem<Key, Data>[size] ; } / returnthe lef subtree ofan i / t tem

283

C++ Programming

Copyright 1998 Pragmatix Software

template <class Key,classData> Page<Key, Data>*& Page<Key, Data>::Left (constintofI tem) { returnofI tem <= 0 ? lef : tems[of tem -1].Subtree() ti I ; } / returnthe r / ightsubtree ofan i tem template <class Key,classData> Page<Key, Data>*& Page<Key, Data>::Right(constintofI tem) { returnofI tem < 0 ? lef :i t tems[of tem].Subtree() I ; } / do a binary search on i / tems ofa page / returnstrue i successfuland falseotherwise / f template <class Key,classData> BoolPage<Key, Data>::BinarySearch (Key key,int&idx) { int = 0; low int high = used -1; int mid; do { mid = ( + high)/2; low i (key <= i f tems[mid].KeyOf() ) high = mid -1; / restr c tolower half / it i (key >= i f tems[mid].KeyOf() ) low = mid + 1; / restr c toupper half / it } while( <= high); low Boolfound = low -high > 1; idx= found ? mid :high; returnfound; } / copy a setofi / tems from page topage template <class Key,classData> intPage<Key, Data>::CopyItems (Page<Key, Data> *dest,constintsrcIdx, constintdestIdx,constintcount) { for(registeri= 0;i< count;++i) / straightcopy / dest>items[destIdx+ i = i ] tems[src + i ; Idx ] returncount; } / insertan i / tem intoa page template <class Key,classData> BoolPage<Key, Data>:: Insert tem ( tem<Key, Data> &item, intatIdx) I I {

www.pragsoft.com

Solutions to Exercises

284

for(registeri= used;i> atIdx;-i -) i tems[i = i ] tems[i-1]; i tems[at Idx]= i tem; return++used >= size; } / deletean i / tem from a page

/ shif r / t ight / insert / / overf / low?

template <class Key,classData> BoolPage<Key, Data>::Delete tem ( atIdx) I int { for(registeri= atIdx;i< used -1;++i) / shif lef / t t i tems[i = i ] tems[i+ 1]; return-used < size/2; / underf / low? } / recurs / ivelyprinta page and i subtrees ts template <class Key,classData> void Page<Key, Data>::Pr tPage (ostream& os,constintmargin) in { char margBuf[128]; / buildthe margin str / ing: for( i= 0;i<= margin;++i) int margBuf[i = '' ] ; margBuf[ ] ' ' i = \0 ; / printthe lef - ost chi : / tm ld i (Left != 0) f (0) Left(0)>PrintPage(os,margin + 8); / printpage and remaining chi / ldren: for( = 0;i< used;++i){ i os << margBuf; os << (*th ) i << ' ' is [ ] \n ; i (Right( ) 0) f i!= Right( ) PrintPage(os,margin + 8); i> } } template <class Key,classData> BTree<Key, Data>::BTree (constintord):order(ord) { root= 0; bufP = new Page<Key, Data>(2 * order+ 2); } template <class Key,classData> void BTree<Key, Data>:: Insert (Key key,Data data) { I tem<Key, Data> i tem(key,data), *receive; i (root== 0) { f / empty tree /

285

C++ Programming

Copyright 1998 Pragmatix Software

root= new Page<Key, Data>(2 * order) ; root>Insert tem(i I tem,0); } elsei ((receive= InsertAux(&item,root) != 0) { f ) Page<Key, Data> *page = new Page<Key, Data>(2 * order) / new root ; / page->Insert tem(*receive,0); I page->Left(0)= root; root= page; } } template <class Key,classData> void BTree<Key, Data>::Delete(Key key) { Boolunderf low; DeleteAux1(key,root, underf low); i (underf && rootf low >Used()== 0) { / dispose root / Page<Key, Data> *temp = root; root= root>Left(0) ; deletetemp; } } template <class Key,classData> BoolBTree<Key, Data>::Search (Key key,Data &data) { I tem<Key, Data> *item = SearchAux(root key); , i ( tem == 0) fi returnfalse; data = i tem->DataOf() ; returntrue; } template <class Key,classData> ostream& operator<< (ostream& os,BTree<Key, Data> &tree) { i (tree. f root!= 0) tree. root>PrintPage(os,0); returnos; } / recurs / ivelyfreea page and i subtrees ts template <class Key,classData> void BTree<Key, Data>::FreePages (Page<Key, Data> *page) { i (page != 0) { f FreePages(page>Left(0) ; ) for(registeri= 0;i< page->Used();++i) FreePages(page>Right( ) ; i) deletepage; } }

www.pragsoft.com

Solutions to Exercises

286

/ recurs / ivelysearch the treeforan i tem with matching key template <class Key,classData> I tem<Key, Data>* BTree<Key, Data>:: SearchAux (Page<Key, Data> *tree,Key key) { int idx; I tem<Key, Data> *i tem; i (tree== 0) f return0; i (treef >BinarySearch(key,idx)) return&((*tree) idx] ; [ ) returnSearchAux(idx< 0 ? tree>Left(0) :tree>Right( , idx) key); } / insertan i / tem intoa page and spl t page i i overf i the ft lows template <class Key,classData> I tem<Key, Data>* BTree<Key, Data>:: InsertAux ( tem<Key, Data> *i I tem, Page<Key, Data> *page) { Page<Key, Data> *chi ; ld int idx; i (pagef >BinarySearch( temi >KeyOf() idx)) , return0; / already intree / i ((chi = page->Right( ) 0) f ld idx) != i tem = InsertAux( tem,chi ; i ld)

/ chi isnot a leaf / ld

i ( tem != 0) { fi / page isa leaf or passed up / , i (pagef >Used()< 2 * order){ / insertinthe page / page->Insert tem(*i I tem,idx+ 1); } else { / page isful , i / lspl t Page<Key, Data> *newP = new Page<Key, Data>(2 * order) ; bufP>Used()= page->CopyItems(bufP,0,0,page->Used()) ; bufP>Insert tem(*i I tem,idx+ 1); intsize= bufP>Used(); inthalf= size/2; page->Used()= bufP>CopyItems(page,0,0,half ; ) newP->Used()= bufP>CopyItems(newP, half+ 1,0,size-half-1); newP->Left(0)= bufP>Right(hal ) f; *item = (*bufP)[hal ] f; i tem->Subtree()= newP; returni tem; } } / the mid i / tem

287

C++ Programming

Copyright 1998 Pragmatix Software

return0; } / deletean i / tem from a page and dealwith underf lows template <class Key,classData> void BTree<Key, Data>::DeleteAux1 (Key key, Page<Key, Data> *page,Bool&underf low) { int idx; Page<Key, Data> *chi ; ld underf = false; low i (page == 0) f return; i (pagef >BinarySearch(key,idx)){ i ((chi = page->Left( ) f ld idx) == 0) { / page isa leaf / underf = page->DeleteI low tem(idx) ; } else { / page isa subtree / / deletefrom subtree: / DeleteAux2(page,chi , ld idx,underf low); i (underf f low) Underflow(page,chi , -1,underf ld idx low); } } else{ / isnot on thispage / chi = page->Right( ; ld idx) DeleteAux1(key,chi , ld underf low); / should be inchi / ld i (underf f low) Underf low(page,chi , ld idx,underf low); } } / deletean i / tem and dealwith underf lows by borrowing /i / tems from neighboring pages or merging two pages template <class Key,classData> void BTree<Key, Data>::DeleteAux2 (Page<Key, Data> *parent, Page<Key, Data> *page, constintidx,Bool&underf low) { Page<Key, Data> *chi = page->Right(pageld >Used()-1); i (chi != 0) { f ld / page isnot a leaf / DeleteAux2(parent,chi , ld idx,underf low);/ go anotherleveldown / i (underf f low) Underf low(page,chi , ld page->Used()-1,underf low); } else{ / page isa leaf / / save right / : Page<Key, Data> *r ight= parent>Right( ; idx) / borrow an i / tem from page forparent: page->CopyItems(parent,page->Used()-1,idx,1); / restoreright / : parent>Right( idx)= right ;

www.pragsoft.com

Solutions to Exercises

288

underf = page->DeleteI low tem(page>Used()-1); } } / handle underf / lows template <class Key,classData> void BTree<Key, Data>::Underf (Page<Key, Data> *page, low Page<Key, Data> *chi , ld intidx,Bool&underf low) { Page<Key, Data> *lef = t idx< page->Used()-1 ? chi :page->Left( ; ld idx) Page<Key, Data> *r ight= lef == chi ? page->Right(++idx):chi ; t ld ld / copy contentsoflef , / tparenti tem,and rightonto bufP: intsize= lef - CopyItems(bufP,0,0,lef - Used()) t > t > ; (*bufP) i ] (*page)[ ; [s ze = idx] bufP>Right(s ize++) = right>Left(0) ; size+= right>CopyItems(bufP,0,size,right>Used()) ; i (s > 2 * order){ f ize / distr / ibutebufP i tems between lef and right t : inthalf= size/2; lef - Used()= bufPt> >CopyItems(lef , 0,half ; t0, ) r ight>Used()= bufP>CopyItems(r ight half+ 1,0,size-half-1); , r ight>Left(0)= bufP>Right(hal ) f; (*page)[ idx]= (*bufP)[hal ] f; page->Right( idx)= r ight ; underf = false; low } else{ / merge,and freethe r / ightpage: lef - Used()= bufPt> >CopyItems(lef , 0,size) t0, ; underf = page->DeleteI low tem(idx) ; deleter ight ; } } / -----------------------------/ -----------------------------template <class Key,classData> classBStar:publicBTree<Key, Data> { public : BStar (constintorder):BTree<Key, Data>(order){} vir tual voidInsert (Key key,Data data); protected: vir I tual tem<Key, Data>* vir I tual tem<Key, Data>*

InsertAux ( tem<Key, Data> *i I tem, Page<Key, Data> *page); Overf low ( tem<Key, Data> *i I tem, Page<Key, Data> *page, Page<Key, Data> *chi , idx) ld int ;

};

289

C++ Programming

Copyright 1998 Pragmatix Software

/ insertwith overf / low/underf handling low template <class Key,classData> void BStar<Key,Data>:: Insert(Key key,Data data) { I tem<Key, Data> i tem(key,data); I tem<Key, Data> *overf low; Page<Key, Data> *lef , ight t*r ; Booldummy; i (root== 0) { f / empty tree / root= new Page<Key, Data>(2 * order) ; root>Insert tem(i I tem,0); } elsei ((overf = InsertAux(&item,root) != 0) { f low ) lef = root; t / rootbecomes a lef chi / t ld root= new Page<Key, Data>(2 * order) ; r ight= new Page<Key, Data>(2 * order) ; root>Insert tem(*overf I low,0); root>Left(0)= lef ; t / the lef - ost chi ofroot / tm ld root>Right(0)= r ight / the rightchi ofroot ; / ld r ight>Left(0)= overf >Subtree() low; /r / ightisunderf lown (s == 0): ize Underflow(root r , ight 0,dum my); , } } / insertsand dealswith overf / lows template <class Key,classData> I tem<Key, Data>* BStar<Key,Data>:: InsertAux ( tem<Key, Data> *item, I Page<Key, Data> *page) { Page<Key, Data> *chi ; ld int idx; i (pagef >BinarySearch( temi >KeyOf() idx)) , return0; / already intree / i ((chi = page->Right( ) 0) { f ld idx) != / chi not a leaf / ld : i (( tem = InsertAux( tem,chi ) 0) f i i ld) != returnOverflow( tem,page,chi , i ld idx) ; } elsei (pagef >Used()< 2 * order){ / i / tem f t innode is page->Insert tem(*i I tem,idx+ 1); } else{ / node isful / l intsize= page->Used(); bufP>Used()= page->CopyItems(bufP,0,0,size) ; bufP>Insert tem(*i I tem,idx+ 1); bufP>CopyItems(page,0,0,size) ; *i tem = (*bufP)[s ze ; i ] returni tem; } return0; }

www.pragsoft.com

Solutions to Exercises

290

/ handles underf / lows template <class Key,classData> I tem<Key, Data>* BStar<Key,Data>::Overf ( tem<Key, Data> *i low I tem, Page<Key, Data> *page, Page<Key, Data> *chi , idx) ld int { Page<Key, Data> *lef = t idx< page->Used()-1 ? chi :page->Left( ; ld idx) Page<Key, Data> *r ight= lef == chi ? page->Right(++idx):chi ; t ld ld / copy lef , / toverf lown and parenti tems,and rightintobuf: bufP>Used()= lef - CopyItems(bufP,0,0,lef - Used()) t> t> ; i (chi == lef ){ f ld t bufP>Insert tem(*i I tem,bufP>Used()) ; bufP>Insert tem((*page)[ , I idx] bufP>Used()) ; bufP>Right(bufP>Used()-1) = right>Left(0) ; bufP>Used()+= r ight>CopyItems(bufP,0,bufP>Used(),r ight>Used()) ; } else{ bufP>Insert tem((*page)[ , I idx] bufP>Used()) ; bufP>Right(bufP>Used()-1) = right>Left(0) ; bufP>Used()+= r ight>CopyItems(bufP,0,bufP>Used(),r ight>Used()) ; bufP>Insert tem(*i I tem,bufP>Used()) ; } i (bufPf >Used()< 4 * order+ 2) { / distr / ibutebuf between lef and right t : intsize= bufP>Used(),half ; lef - Used()= bufPt> >CopyItems(lef , 0,half= size/2) t0, ; r ight>Used()= bufP>CopyItems(r ight half+ 1,0,size-half-1); , r ight>Left(0)= bufP>Right(hal ) f; (*page)[ idx]= (*bufP)[hal ] f; page->Right( idx)= r ight ; return0; } else{ / spl t 3 pages: / i int Page<Key, Data> *newP = new Page<Key, Data>(2 * order) ; int mid1,mid2; mid1 = lef - Used()= bufPt> >CopyItems(lef , 0,(4 * order+ 1) /3); t0, mid2 = right>Used()= bufP>CopyItems(r ight mid1 + 1,0,4 * order/3); , mid2 += mid1 + 1; newP->Used()= bufP>CopyItems(newP, mid2 + 1,0,(4 * order+ 2) /3); r ight>Left(0)= bufP>Right(mid1); bufP>Right(mid1)= r ight ; newP->Left(0)= bufP>Right(mid2); bufP>Right(mid2)= newP; (*page)[ idx]= (*bufP)[mid2]; i (pagef >Used()< 2 * order){ page->Insert tem((*bufP) I [mid1], idx) ;

291

C++ Programming

Copyright 1998 Pragmatix Software

return0; } else { *item = (*page)[page>Used()-1]; (*page)[page>Used()-1] = (*bufP) [mid1]; returni tem; } } }

10.1

enum PType {controlPack,dataPack,diagnosePack}; enum Bool {false,true}; classPacket{ public : / .. /. PType Type BoolValid };

(void) (void)

{returndataPack;} {returntrue;}

classConnection { public : / .. /. BoolActive (void) }; classInact iveConn {}; classInval idPack {}; classUnknownPack {};

{returntrue;}

void ReceivePacket(Packet*pack,Connection*c) throw(Inact iveConn,Inval idPack,UnknownPack) { i (!cf >Active() ) throw Inact iveConn() ; i (!packf >Valid( ) ) throw Inval idPack() ; switch (pack>Type()){ case controlPack: / .. /. break; case dataPack: / .. /. break; case diagnosePack: / .. /. break; default : / .. /. throw UnknownPack(); } }

10.2

#include <iostream.h> classDimsDontMatch classBadDims {}; {};

www.pragsoft.com

Solutions to Exercises

292

classBadRow {}; classBadCol {}; classHeapExhausted {}; classMatrix{ public : Matrix Matrix (constshortrows,constshortcols) ; (constMatrix&); ~Matrix (void) {deleteelems;} double& operator() (constshortrow,constshortcol) ; Matrix& operator= (constMatrix&);

fr iend ostream& operator<< (ostream&, Matrix&); fr iend Matrix operator + (Matr ix&,Matrix&); fr iend Matrix operator (Matr ix&,Matrix&); fr iend Matrix operator * (Matr ix&,Matrix&); constshort Rows (void) {returnrows;} constshort Cols (void) {returncols;} private: constshort constshort double }; rows; / matrixrows / cols; / matrixcolumns / *elems; / matrixelements /

Matrix :Matr (constshortr,constshortc):rows(r) cols(c) : ix , { i (rows <= 0 | cols<= 0) f | throw BadDims(); elems = new double[rows * cols] ; i (elems == 0) f throw HeapExhausted() ; } Matrix :Matr (constMatrix&m) :rows(m.rows),cols(m.cols) : ix { intn = rows * cols; i (rows <= 0 | cols<= 0) f | throw BadDims(); elems = new double[n] ; i (elems == 0) f throw HeapExhausted() ; for(regis i= 0;i< n;++i) ter / copy elements / elems[i = m.elems[i] ] ; } double& Matrix: :operator()(constshortrow,constshortcol) { i (row <= 0 | row > rows) f | throw BadRow(); i (col<= 0 | col> cols) f | throw BadCol() ; returnelems[(row -1)*cols+ (col-1)];

293

C++ Programming

Copyright 1998 Pragmatix Software

} Matrix& Matrix :operator= (constMatrix&m) : { i (rows == m.rows && cols== m.cols){ / must match f / intn = rows * cols; for(registeri= 0;i< n;++i) / copy elements / elems[i] m.elems[i ; = ] } else throw DimsDontMatch() ; return*this ; } ostream& operator<< (ostream &os,Matrix&m) { for(regis r= 1;r<= m.rows;++r) { ter for( c = 1;c <= m.cols;++c) int os << m(r,c)<< ' t ; \' os << ' ' \n ; } returnos; } Matrixoperator+ (Matr &p, Matrix&q) ix { i (p.rows != q.rows | p.cols!= q.cols) f | throw DimsDontMatch() ; Matrixm(p.rows,p.cols) ; i (p.rows == q.rows && p.cols== q.cols) f for(registerr= 1;r<= p.rows;++r) for(regis c = 1;c <= p.cols ++c) ter ; m(r,c)= p(r ) q(r ) ,c + ,c ; returnm; } Matrixoperator-(Matr &p, Matrix&q) ix { i (p.rows != q.rows | p.cols!= q.cols) f | throw DimsDontMatch() ; Matrixm(p.rows,p.cols) ; i (p.rows == q.rows && p.cols== q.cols) f for(registerr= 1;r<= p.rows;++r) for(regis c = 1;c <= p.cols ++c) ter ; m(r,c)= p(r ) q(r ) ,c - ,c ; returnm; } Matrixoperator* (Matr &p, Matrix&q) ix { i (p.cols!= q.rows) f throw DimsDontMatch() ; Matrixm(p.rows,q.cols) ; i (p.cols== q.rows) f for(registerr= 1;r<= p.rows;++r)

www.pragsoft.com

Solutions to Exercises

294

for(regis c = 1;c <= q.cols ++c) { ter ; m(r,c)= 0.0; for(registeri= 1;i<= p.cols ++i) ; m(r,c)+= p(r ) q(r ) ,c * ,c ; } returnm; }

295

C++ Programming

Copyright 1998 Pragmatix Software

Das könnte Ihnen auch gefallen