inheritance and data structures
TRANSCRIPT
![Page 1: Inheritance and data structures](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/1.jpg)
Inheritance and datastructures
![Page 2: Inheritance and data structures](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/2.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/3.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/4.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/5.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/6.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/7.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/8.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/9.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/10.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/11.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/12.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/13.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/14.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/15.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/16.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/17.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/18.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/19.jpg)
// 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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/20.jpg)
)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/21.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/22.jpg)
#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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/23.jpg)
// 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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/24.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/25.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/26.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/27.jpg)
// 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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/28.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/29.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/30.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/31.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/32.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/33.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/34.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/35.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/36.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/37.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/38.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/39.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/40.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/41.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/42.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/43.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/44.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/45.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022042403/625da29951f0be637a5218a5/html5/thumbnails/46.jpg)
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;
};