46
Inheritance and data structures

Inheritance and data structures

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Inheritance and data structures

Inheritance and datastructures

Page 2: Inheritance and data structures

Task

Transform an infix expression to a postfix expression (Reverse Polish Notation - RPN) and calculate its value.

2Teréz A. Várkonyi: Object-oriented programming

5+(11+26)*(43-4) 5 11 26 + 43 4 - * + 1448

To transform an infix expression and to evaluate it, usually two stacks are needed. In the first one, the operators and the open parentheses are stored. In the second one, the operands and the partial results are put.

infix expression postfix expression value

Page 3: Inheritance and data structures

1. Tokenize the infix expression and put the tokens into an x sequence.

2. Convert to Polish notation: x is converted into a y sequence in which the tokens are in postfix form. For the conversion, a stack is used.

3. Evaluate the y sequence by using a second stack.

Plan

3Teréz A. Várkonyi: Object-oriented programming

*

*

11( + 26 ) * ( 43 - 4 )x:

input: 5+(11+26)*(43-4)

2611 + 43 4 -y:

result: 1448

11 ( 26 -4)43

+5

5 +

tokenization

conversion to postfix form

+5

tokens:

evaluation

It is enough to create one instanceof some of the tokens and later on,they can be referred multiple times.

Tokens are objects, only their address isstored in the sequence.

Page 4: Inheritance and data structures

Objects to be used

string: an infix expression given in a standard input (fstream)

tokens: specific tokens (Token), as operands (Operand), operators (Operator), and parentheses (LeftP, RightP)

sequences: pointers pointing at the tokens (vector<Token*>): for the tokenized infix expression (x),for the tokenized postfix expression (y)

stacks: for storing the pointers of the tokens (Stack<Token*>),for storing the numbers (Stack<int>)

4Teréz A. Várkonyi: Object-oriented programming

Page 5: Inheritance and data structures

vector<Token*> x;

// Tokenization…

// Transforming into Polish notationvector<Token*> y;Stack<Token*> s…

// EvaluationStack<int> v;…

deallocateToken(x);

int main() {char ch;do {

cout << "Give me an arithmetic expression:\n";vector<Token*> x;try{// Tokenization

…// Transforming into Polish notation

vector<Token*> y;Stack<Token*> s…

// EvaluationStack<int> v;…

} catch (MyException ex) { }deallocateToken(x);

cout << "\nDo you continue? Y/N";cin >> ch;

} while ( ch!='n' && ch!='N' );return 0;

}

MyException::Interrupt exceptionmay be raised anytime

5Teréz A. Várkonyi: Object-oriented programming

Main program

void deallocateToken(vector<Token*> &x){

for( Token* t : x ) delete t;}

main.cpp

enum MyException { Interrupt };

frees the memoryallocation of the tokens

token instantiation

Page 6: Inheritance and data structures

Token class and its childrenToken

+is_Operand() : bool {virtual, query}+is_Operator(): bool {virtual, query}+is_LeftP() : bool {virtual, query}+is_RightP() : bool {virtual, query}+read(stream) : Token*+to_String() : string {virtual}

Operand- val:int

+is_Operand() : bool+to_String() : string+value() : int {query}

LeftP

+is_LeftP() : bool+to_String() : string

Operator- op:char

+is_Operator() : bool+to_String() : string+evaluate(int,int) : int {query}+priority() : int {query}

RightP

+is_RightP() : bool+to_String() : string

alternative type

tokenizer

6Teréz A. Várkonyi: Object-oriented programming

return false

it reads thenext token

return truereturn truereturn truereturn true

abstract methodabstract class

Page 7: Inheritance and data structures

Abstract class, interface❑ Abstract class is never instantiated, it is used only

as a base class for inheritance.

‒ name of the abstract class is italic.

❑ A class is abstract if

• its constructors are not public, or

• at least one method is abstract (it is not implemented and it is overridden in a child)

− name of the abstract method is also italic

7Teréz A. Várkonyi: Object-oriented programming

<class>

<interface>

❑ Pure abstract classes are called interfaces, none of their methods are implemented.

❑ When a class implements all of the abstract methods of an interface, it realizes the interface.

<child class>

<base class>

Page 8: Inheritance and data structures

class Token{public:

class IllegalElementException{private:

char _ch;public:

IllegalElementException(char c) : _ch(c){}char message() const { return _ch;}

};virtual ~Token();virtual bool is_LeftP() const { return false; }virtual bool is_RightP() const { return false; }virtual bool is_Operand() const { return false; }virtual bool is_Operator() const { return false; }virtual bool is_End() const { return false; }

virtual std::string to_String() const = 0;

friendstd::istream& operator>>(std::istream&, Token*&);

}; token.h

not presented inthe specification

8Teréz A. Várkonyi: Object-oriented programming

Token class

for exception handling

Why is the destructor virtual?

Page 9: Inheritance and data structures

class Operand: public Token{private:

int _val;public:

Operand(int v) : _val(v) {}

bool is_Operand() const override { return true; }

std::string to_String() const override {std::ostringstream ss; ss << _val; return ss.str();

}

int value() const { return _val; }};

conversion

9Teréz A. Várkonyi: Object-oriented programming

Operand class

token.h

Page 10: Inheritance and data structures

class LeftP : public Token{

public:

bool is_LeftP() const override { return true; }

std::string to_String() const override { return "("; }};

10Teréz A. Várkonyi: Object-oriented programming

LeftP class(one instance is enough)

LeftP(){}

static LeftP *_instance;

static LeftP *instance() {

return _instance;}

private:

LeftP *LeftP::_instance = nullptr;

if ( _instance == nullptr ) _instance = new LeftP();

private constructor

creator method

points at the onlyone instance

private constructoris called here

token.h

token.cpp

Page 11: Inheritance and data structures

Singleton design pattern

❑ The class is instantiated only once, irrespectively of the number of

instantiation requests.

11Teréz A. Várkonyi: Object-oriented programming

Singleton- instance : Singleton

- Singleton()+ instance() : Singleton+ destroy() : void

if instance = nil then instance := new Singleton()

endifreturn instance

Design patterns are class diagram patterns that help object-oriented modeling. They play a

significant role in reusability, modifiability, and ensuring efficiency.

class-level attribute:refers to one instanceprivate constructor:

the class cannot beinstantiated directly

class-level method for serving theinstantiation requests:it returns an instance

Page 12: Inheritance and data structures

class RightP : public Token {private:

RightP(){}static RightP *_instance;

public:static RightP *instance() {

if ( _instance == nullptr ) _instance = new RightP();return _instance;

}bool is_ RightP() const override { return true; }std::string to_String() const override { return ")"; }

};

12Teréz A. Várkonyi: Object-oriented programming

RightP, End singleton classes

RightP *RightP::_instance = nullptr;End *End::_instance = nullptr;

class End : public Token {private:

End(){}static End *_instance;

public:static End *instance() {

if ( _instance == nullptr ) _instance = new End();return _instance;

}bool is_ End() const override { return true; }std::string to_String() const override { return ";"; }

};

token.h

token.cpp

Page 13: Inheritance and data structures

class Operator: public Token{private:

char _op; public:

Operator(char o) : _op(o) {}

bool is_Operator() const override { return true; }std::string to_String() const override {

string ret;ret = _op;return ret;

}virtual int evaluate(int leftValue, int rightValue) const;virtual int priority() const;

};

13Teréz A. Várkonyi: Object-oriented programming

Operator class

conversion

token.h

Page 14: Inheritance and data structures

14Teréz A. Várkonyi: Object-oriented programming

Methods of class Operator

int Operator::evaluate(int leftValue, int rightValue) const{

switch(_op){case '+': return leftValue+rightValue;case '-': return leftValue-rightValue;case '*': return leftValue*rightValue;case '/': return leftValue/rightValue;default: return 0;

}}

int Operator::priority() const{

switch(_op){case '+': case '-': return 1;case '*' : case '/': return 2;default: return 3;

}}

SOLID

pen-Close

SOLID

this code does notsatisfy the open-closeprinciple

token.cpp

ingle responsibility

iskov substitution

epedency inversion

nterface segregation

Page 15: Inheritance and data structures

Operator classesOperator

- op:char# Operator(c:char)+ is_Operator() : bool {override}+ to_String() : string {override, query}+ evaluate(l,r:int): int {virtual, query}+ priority() : int {virtual, query}

<<singleton>>OperatorAdd

+ evaluate(l,r:int) : int{override, query}+ priority() : int{override, query}

<<singleton>>

OperatorMul

+ evaluate(l,r:int) : int{override, query}+ priority() : int{override, query}

<<singleton>>OperatorSub

+ evaluate(l,r:int) : int{override, query}+ priority() : int{override, query}

<<singleton>>

OperatorDiv

+ evaluate(l,r:int) : int{override, query}+ priority() : int{override, query}

15Teréz A. Várkonyi: Object-oriented programming

return truereturn op

return 2return 2return 1return 1

op := c

return 3

return l+r return l-r return l*r return l/r

protected to becalled in the childrenclasses

Page 16: Inheritance and data structures

class Operator: public Token{private:

char _op; protected:

Operator(char o) : _op(o) {}public:

bool is_Operator() const override { return true; }std::string to_String() const override {

string ret;ret = _op;return ret;

}virtual int evaluate(int leftValue, int rightValue) const = 0;virtual int priority() const { return 3; }

};

16Teréz A. Várkonyi: Object-oriented programming

token.h

Abstract Operator class

Page 17: Inheritance and data structures

class OperatorAdd: public Operator{private:

OperatorAdd() : Operator('+') {}static OperatorAdd *_add;

public:static OperatorAdd * instance(){

if ( _add == nullptr ) _add = new OperatorAdd();return _add;

}int evaluate(int leftValue, int rightValue) const override {

return leftValue + rightValue; }int priority() const override { return 1; }

};

17Teréz A. Várkonyi: Object-oriented programming

Singleton operator classes

class OperatorSub: public Operator{private:

OperatorSub() : Operator('-') {}static OperatorSub *_sub;

public:static OperatorSub * instance(){

if ( _sub == nullptr ) _sub = new OperatorSub();return _sub;

}int evaluate(int leftValue, int rightValue) const override {

return leftValue - rightValue; }int priority() const override { return 1; }

};

class OperatorMul: public Operator{private:

OperatorMul() : Operator('*') {}static OperatorMul *_mul;

public:static OperatorMul * instance(){

if ( _mul == nullptr ) _mul = new OperatorMul();return _mul;

}int evaluate(int leftValue, int rightValue) const override {

return leftValue * rightValue; }int priority() const override { return 2; }

};

class OperatorDiv: public Operator{private:

OperatorDiv() : Operator('/') {}static OperatorDiv *_div;

public:static OperatorDiv * instance(){

if ( _div == nullptr ) _div = new OperatorDiv();return _div;

}int evaluate(int leftValue, int rightValue) const override {

return leftValue / rightValue; }int priority() const override { return 2; }

};OperatorAdd* OperatorAdd::_add = nullptr;OperatorSub* OperatorAdd::_sub = nullptr;OperatorMul* OperatorAdd::_mul = nullptr;OperatorDiv* OperatorAdd::_div = nullptr;

No need for conditionals

token.cpp

token.h

Page 18: Inheritance and data structures

istream& operator>> (istream &s, Token* &t){char ch;s >> ch;switch(ch){

case '0' : case '1' : case '2' : case '3' : case '4':case '5' : case '6' : case '7' : case '8' : case '9':

s.putback(ch);int intval; s >> intval;t = new Operand(intval); break;

case '+' : t = OperatorAdd::instance(); break;case '-' : t = OperatorSub::instance(); break;case '*’ : t = OperatorMul::instance(); break;case '/' : t = OperatorDiv::instance(); break;case '(' : t = LeftP::instance(); break;case ')' : t = RightP::instance(); break;case ';' : t = End::instance(); break;default: if(!s.fail()) throw new Token::IllegalElementException(ch);

}return s;

}

an expression isended by a semicolon

back to the a buffer

18Teréz A. Várkonyi: Object-oriented programming

Tokenizer operator

singletons

token.cpp

Page 19: Inheritance and data structures

// Tokenization

try{Token *t;cin >> t;while( !t->is_End() ){

x.push_back(t);cin >> t;

}}catch(Token::IllegalElementException *ex){

cout << "Illegal character: " << ex->message() << endl;delete ex;throw Interrupt;

}

the reading throws it

token reading

19Teréz A. Várkonyi: Object-oriented programming

Tokenization

main.cpp

Page 20: Inheritance and data structures

)

20Teréz A. Várkonyi: Object-oriented programming

Convert to Polish notationLeft parentheses and operators are put into a stack. The operator withlower priority has to swap with the higher priority operators in the stack.Every other token is copied into the output sequence. In case of a rightparenthesis, the content of the stack until the first left parenthesis is putinto the output sequence. When we reach the end of the input sequence,the content of the stack is put into the output sequence.

+

4-43(*)26+11(+5

-

+

*

Page 21: Inheritance and data structures

x.first() ; y:=<>

x.end()

t := x.current()

x.next()

t.is_Operand() t.is_LeftP() t.is_RightP() t.is_Operator()

y.push_back(t)

s.top().is_LeftP()

s.empty()

s.top().is_LeftP()

s.top().priority()≧ t.priority()s.push(t) y.push_back(s.top())

s.pop() y.push_back(s.top())

s.pop()

s.pop() s.push(t)

y.push_back(s.top()) ; s.pop()

s.empty()

x.next()

21Teréz A. Várkonyi: Object-oriented programming

Page 22: Inheritance and data structures

#include <stack>

enum StackExceptions{EMPTYSTACK};

template <typename Item>class Stack{private:

std::stack<Item> s;public:

void pop() {if( s.empty() ) throw EMPTYSTACK;s.pop();

}Item top() const {

if( s.empty() ) throw EMPTYSTACK;return s.top();

}bool empty() { return s.empty(); }void push(const Item& e) { s.push(e); }

};

22Teréz A. Várkonyi: Object-oriented programming

Template for the stack

Stack

+empty() : bool+push(Item) : void+pop() : void+top() : Item

if s.empty() then errorelse return s.top()

Item

std::stack

+empty() : bool+push(Item) : void+pop() : void+top() : Item

- s

Item

if s.empty() then errorelse s.pop()

s.push(e)

return s.empty()

stack.hpp

Page 23: Inheritance and data structures

// Transforming into polish form

vector<Token*> y;Stack<Token*> s;

for( Token *t : x ){if ( …else if ( …else if ( …else if ( …

}while( !s.empty() ){

if( s.top()->is_LeftP() ){cout << "Syntax error!\n"; throw Interrupt;

}else{ y.push_back(s.top());s.pop();

}}

error when we have more leftparentheses than right

enumeration

see the next slide

23Teréz A. Várkonyi: Object-oriented programming

Creating the postfix expression

main.cpp

Page 24: Inheritance and data structures

if ( t->is_Operand() ) y.push_back(t);else if ( t->is_LeftP() ) s.push(t);else if ( t->is_RightP() ){

try{while( !s.top()->is_LeftP() ) {

y.push_back(s.top());s.pop();

}s.pop();

}catch(StackExceptions ex){if(ex==EMPTYSTACK){

cout << "Syntax error!\n"; throw Interrupt;

}}

}else if ( t->is_Operator() ) {while( !s.empty() && s.top()->is_Operator() &&

((Operator*)s.top())->priority()>=((Operator*)t)->priority() ) {

y.push_back(s.top()); s.pop();

}s.push(t);

}

”static casting”: s.top()->priority() isnot good, as in Token there is no priority().

error when we have more rightparentheses than left

24Teréz A. Várkonyi: Object-oriented programming

Creating the postfix expression

main.cpp

Page 25: Inheritance and data structures

11 +26 *43 -4

37

39

25Teréz A. Várkonyi: Object-oriented programming

5 +

1443

1448

Evaluation of the postfix expressionOperands of the postfix expression (in order of reading) are put into a stack. In case of operator, the top two numbers are taken and processedaccording to the type of the operator. The result is put back into the stack. At the end of the process, the result can be found in the stack.

Page 26: Inheritance and data structures

y.first()

y.end()

t := y.current()

v.push(t)

rightOp := v.top(); v.pop()leftOp := v.top(); v.pop()v.push(t.evaluate(leftOp, rightOp))

y.next()

z := v.top(); v.pop()

t.is_operand()

26Teréz A. Várkonyi: Object-oriented programming

Evaluation

Page 27: Inheritance and data structures

// Evaluationtry{

Stack<int> v;for( Token *t : y ){

if ( t->is_Operand() ) {v.push( ((Operand*)t)->value() );

} else{int rightOp = v.top(); v.pop();int leftOp = v.top(); v.pop();v.push(((Operator*)t)->evaluate(leftOp, rightOp));

}}int result = v.top(); v.pop();if( !v.empty() ){

cout << "Syntax error!";throw Interrupt;

}cout << "The value of the expression: " << result << endl;

}catch( StackExceptions ex ){if( ex==EMPTYSTACK ){

cout << "Syntax error! "; throw Interrupt;

}}

static casting

static casting

error when we havetoo many operands

enumeration

27Teréz A. Várkonyi: Object-oriented programming

Evaluation

error when we do not haveenough operands main.cpp

Page 28: Inheritance and data structures

token.h

stack.hpp

token.cpp main.cpp

Stack<Item>

TokenOperandOperatorOperatorAdd, OperatorSub, OperatorMul, OperatorDivLeftP, RightPEnd

28Teréz A. Várkonyi: Object-oriented programming

Package diagram

main()enum MyException { … };deallocateToken()

Page 29: Inheritance and data structures

Task: traversal of a binary treeRead some numbers from a standard input and build randomly a binary treefrom them. Then print the tree’s elements to a standard output based ondifferent traversal strategies. Finally,• sum up the internal nodes, • find the maximums of the internal nodes and all of the nodes,• find the ”first” even element!

The tree is planned so that the summation, maximum search, and linearsearch are implemented easily. To be able to change the type of the nodes, thetree becomes a template.

29Teréz A. Várkonyi: Object-oriented programming

2

3 4

7 15 4

8 4

21

max

search

condmax

Page 30: Inheritance and data structures

Chained binary treeclass BinTreeprotected:

LinkedNode *_root;...

};

2

3 3

5 nil nil 4 nil nil 7 nil 1 nil

nil 8 nil nil 4 nil

root

Teréz A. Várkonyi: Object-oriented programming 30

template <typename Item>struct LinkedNode {

LinkedNode *_left;Item _val;LinkedNode *_right;

};

Page 31: Inheritance and data structures

Class diagram

Node# val : Item

+ value() : Item {query}+ is_Leaf() : bool {virtual}+ is_Internal() : bool

Action

+exec(Node*) : void {virtual}

LinkedNode

+ is_Leaf() : bool

BinTree

+ randomInsert(const Item&):void+ preOrder(Action) :void+ inOrder(Action) :void+ postOrder(Action) :void

0..2

*

- *root

Teréz A. Várkonyi: Object-oriented programming 31

has

child

Item

Item

Item

Item

return not is_Leaf()

return left=nil and right = nil

- *left- *right

Page 32: Inheritance and data structures

Template class of a nodetemplate <typename Item>class Node {public:

Item value() const { return _val; }virtual bool is_Leaf() const = 0;bool is_Internal() const { return !is_Leaf(); }virtual ~Node(){}

protected:Node(const Item& v): _val(v){}Item _val;

};template <typename Item> class BinTree;template <typename Item>class LinkedNode: public Node<Item>{public:

friend class BinTree;LinkedNode(const Item& v, LinkedNode *l, LinkedNode *r):

Node<Item>(v), _left(l), _right(r){}bool is_Leaf() const override

{ return _left==nullptr && _right==nullptr; }private:

LinkedNode *_left;LinkedNode *_right;

};

Teréz A. Várkonyi: Object-oriented programming 32

bintree.hpp

BinTree class is defined afterLinkedNode. To avoid circularreference, BinTree is justindicated here.

LinkedNode allows BinTree tosee its private attributes andmethods.

Page 33: Inheritance and data structures

template <typename Item>class BinTree{public:

BinTree():_root(nullptr) {srand(time(nullptr));}~BinTree();

void randomInsert(const Item& e);

void preOrder (Action<Item>*todo){ pre (_root, todo); }void inOrder (Action<Item>*todo){ in (_root, todo); }void postOrder(Action<Item>*todo){ post(_root, todo); }

protected:LinkedNode<Item>* _root;

void pre (LinkedNode<Item>*r, Action<Item> *todo);void in (LinkedNode<Item>*r, Action<Item> *todo);void post (LinkedNode<Item>*r, Action<Item> *todo);

};

Teréz A. Várkonyi: Object-oriented programming 33

Template class of the binary tree

initialization of therandom generator : #include <time.h>#include <cstdlib>

with a given action, starting from the root,they traverse the nodes

bintree.hpp

template <typename Item>class Action{public:

virtual void exec(Node<Item> *node) = 0;virtual ~Action(){}

};

Page 34: Inheritance and data structures

2

3 3

5 nil nil 4 nil nil 7 nil 1 nil

nil 8 nil nil 4 nil

root

Inserting a new node into the tree

nil nil

r

r

r

Right

Left

Left

Teréz A. Várkonyi: Object-oriented programming 34

Page 35: Inheritance and data structures

Inserting a new node into the tree

void BinTree<Item>::randomInsert(const Item& e){

if(_root==nullptr) _root = new LinkedNode<Item>(e, nullptr, nullptr);else {

LinkedNode<Item> *r = _root;int d = rand();while(d&1 ? r->_left!=nullptr : r->_right!=nullptr){

if(d&1) r = r->_left;else r = r->_right;d = rand();

}if(d&1) r->_left = new LinkedNode<Item>(e, nullptr, nullptr);else r->_right= new LinkedNode<Item>(e, nullptr, nullptr);

}}

Teréz A. Várkonyi: Object-oriented programming 35

bintree.hpp

random generator

Is the last bit of the random number 1?

Page 36: Inheritance and data structures

Building the tree

#include <iostream>#include "bintree.hpp"

using namespace std;

int main(){

BinTree<int> t;int i;while(cin >> i){

t.randomInsert(i);}

return 0;}

Teréz A. Várkonyi: Object-oriented programming 36

bintree.hpp

Page 37: Inheritance and data structures

template <typename Item>void BinTree<Item>::pre(LinkedNode<Item> *r, Action<Item> *todo){

if(r==nullptr) return;todo->exec(r);pre(r->_left, todo);pre(r->_right, todo);

}

Preorder traversalr

I.

II. III.

Teréz A. Várkonyi: Object-oriented programming 37

1

2 3

4 nil nil 5 nil nil 6 nil 7 nil

nil 8 nil nil 9 nil

root

bintree.hpp

1 2 4 8 5 3 6 9 7

Page 38: Inheritance and data structures

template <typename Item>void BinTree<Item>::in(LinkedNode<Item> *r, Action<Item> *todo){

if(r==nullptr) return;in(r->_left, todo);todo->exec(r);in(r->_right, todo);

}

Inorder traversalr

II.

I. III.

Teréz A. Várkonyi: Object-oriented programming 38

1

2 3

4 nil nil 5 nil nil 6 nil 7 nil

nil 8 nil nil 9 nil

root

bintree.hpp

8 4 2 5 1 6 9 3 7

Page 39: Inheritance and data structures

template <typename Item>void BinTree<Item>::post(LinkedNode<Item> *r, Action<Item> *todo){

if(r==nullptr) return;post(r->_left, todo);post(r->_right, todo);todo->exec(r);

}

Postorder traversalr

III.

I. II.

Teréz A. Várkonyi: Object-oriented programming 39

1

2 3

4 nil nil 5 nil nil 6 nil 7 nil

nil 8 nil nil 9 nil

root

bintree.hpp

8 4 5 2 9 6 7 3 1

Page 40: Inheritance and data structures

BinTree<int> t = build();

Printer<int> print(cout);

cout << "Preorder traversal :";t.preOrder (&print); cout << endl;

cout << "Inorder traversal :";t.inOrder (&print); cout << endl;

cout << "Postorder traversal :";t.postOrder (&print); cout << endl;

Template class of printingtemplate <typename Item>class Printer: public Action<Item>{public:

Printer(ostream &o): _os(o){};void exec(Node<Item> *node) override {

_os << '[' << node->value() << ']';}

private:ostream& _os;

};

Teréz A. Várkonyi: Object-oriented programming 40

Output operator has to be definedfor the datatype replacing Item.

bintree.hpp

Action

+exec(Node*) : void {virtual}

Printer- os : ostream&+ Printer(o:ostream&)+ exec(node:Node) : void

Item

Item

os << node._val

os := o

Page 41: Inheritance and data structures

template <typename Item>BinTree<Item>::~BinTree(){

DelAction del;post(_root, &del);

}

protected:class DelAction: public Action<Item>{public:

void exec(Node<Item> *node) override {delete node;}};

Teréz A. Várkonyi: Object-oriented programming 41

Destructor: traversal with delete

It works only with postorder!

in BinTree<Item>’s protected part.

bintree.hpp

bintree.hpp

Action

+exec(Node*) : void {virtual}

DelAction

+ exec(node:Node) : void

Item

Item

delete node

Page 42: Inheritance and data structures

Other actions’ classesAction

+exec(Node*) : void {virtual}

Summation- s : int+ exec(node:Node) : void+ value() : int

MaxSelect- m : int+ exec(node:Node) : void+ value() : int

LinSearch- l : bool- elem : int + exec(node:Node): void+ found() : bool+ elem() : int

Teréz A. Várkonyi: Object-oriented programming 42

Item

the attributes are initializedby the constructors

m := max(node.value(), m)

If not l and node.value() mod 2 = 0 then

l := trueelem := node.value()

endif

CondMaxSearch- m : int- l : bool+ exec(node:Node) : void+ value() : int+ found() : bool

if node.is_Leaf() then return endifif not l then

l := truem := node. value()

elsem := max(node.value(), m)

endif

if node.is_Internal() thens := s + node.value()

endif

int

Page 43: Inheritance and data structures

Summation

class Summation: public Action<int>{public:

void Summation():_s(0){}void exec(Node<int> *node) override {

{ if(node->Is_Internal()) _s += node->value(); }int value() const {return _s;}

private:int _s;

};

BinTree<int> t = build();

Summation sum;t.preOrder(&sum);cout << "Sum of the elements of the tree: "

<< sum.value() << endl;

Teréz A. Várkonyi: Object-oriented programming 43

Page 44: Inheritance and data structures

Linear searchclass LinSearch: public Action<int>{public:

void LinSearch():_l(false){}void exec(Node<int> *node) override {

if (!l && node->value ()%2==0){l = true;_elem = node->value();

}}bool found() const {return _l;}int elem() const {return _elem;}

private:bool _l;int _elem;

};

BinTree<int> t = build();

LinSearch search;t.preOrder(&search);

if (search.found()) cout << search.elem() << " is an";else cout << "There is no";cout << " even element in the tree.";

Teréz A. Várkonyi: Object-oriented programming 44

Page 45: Inheritance and data structures

Maximum search

class MaxSelect: public Action<int>{public:

MaxSelect(int &i) : _m(i){}void exec(Node<int> *node) override{ _m = max( _m, node->value() ); }

int value() const {return _m;}private:

int _m;};

template <class Item> class BinTree {…public:

enum Exceptions{NOROOT};Item rootValue() const {

if( _root==nullptr ) throw NOROOT;return _root->value();

}

BinTree<int> t = build();

MaxSelect max(t.rootValue());t.preOrder(&max);

cout << "Maxima of the elements of the tree: " << max.value();

Teréz A. Várkonyi: Object-oriented programming 45

bintree.hpp

It shoud raise an exception ifthe tree is empty (without root)

Page 46: Inheritance and data structures

Conditional maximum search

BinTree<int> t = build();

CondMaxSearch max;t.preOrder(&max);

cout << "Maxima of the elements of the tree: " << endl;if(max.value().l) cout << max.value().m << endl;else cout << "none" << endl;

Teréz A. Várkonyi: Object-oriented programming 46

class CondMaxSearch: public Action<int>{public:

struct Result {int m;bool l;

};CondMaxSearch(){_r.l = false;}virtual void exec(Node<int> *node) {

if(node->is_Leaf()) return;if(!_r.l){

_r.l = true;_r.m = node->value();

}else{_r.m = max( _r.m, node->value() );

}}Result value(){return _r;}

private:Result _r;

};