Download presentation

Presentation is loading. Please wait.

Published bySkyler Lindly Modified about 1 year ago

1
1 CS 162 Introduction to Computer Science Chapter 9 Binary Trees Herbert G. Mayer, PSU Status 11/23/2014

2
2 Syllabus Goal Goal Arithmetic Expressions and Trees Arithmetic Expressions and Trees Infix Without Parentheses Infix Without Parentheses Infix With Parentheses Infix With Parentheses Postfix Without Parentheses Postfix Without Parentheses Prefix Without Parentheses Prefix Without Parentheses Interesting Examples Interesting Examples Use of Postfix Use of Postfix

3
3 Goal Refine understanding C++ pointers by building trees Refine understanding C++ pointers by building trees Tree is a data structure of 0 or more connected nodes, each of which may have up to 2 subtrees Tree is a data structure of 0 or more connected nodes, each of which may have up to 2 subtrees A tree has so called end-nodes and root-nodes A tree has so called end-nodes and root-nodes End-nodes, AKA leaves, have no successor End-nodes, AKA leaves, have no successor Internal nodes, i.e. root-nodes, have 1 or 2 successors, but no more than 2 in a binary tree Internal nodes, i.e. root-nodes, have 1 or 2 successors, but no more than 2 in a binary tree Each node has only one incident pointer, different from a graph! Each node has only one incident pointer, different from a graph! Here we build trees that represent arithmetic expression with dyadic operators, such as: * + - / Here we build trees that represent arithmetic expression with dyadic operators, such as: * + - /

4
4 Arithmetic Expressions and Trees Three typical notations for dyadic operations: Three typical notations for dyadic operations: Infix notation: write as the first the left operand, reading left-to- right, then list the dyadic operator, finally list the right operand Infix notation: write as the first the left operand, reading left-to- right, then list the dyadic operator, finally list the right operand For CPU: Order will not work for code emission, as the CPU needs both operands for processing the operator For humans: requires parentheses for proper operator precedence Note exception: programming language APL Postfix notation: write left operand first, then list the right operand, finally the operator Postfix notation: write left operand first, then list the right operand, finally the operator This order will work for code emission, as operator has both operands available at processing time Needs no parentheses, and still obeys operator precedence Postfix notation AKA Polish Postfix, after Jan Łukasiewicz, 1920 Prefix notation: First list the operator, next the first (left) operand, finally the second (right) operand Prefix notation: First list the operator, next the first (left) operand, finally the second (right) operand

5
5 Arithmetic Expressions and Trees a + x ^ c + a^ xc Infix:( a + ( x ^ c ) ) Postfix:a x c ^ + Prefix:+ a ^ x c ^ stands for exponentiation operator, with highest precedence: higher than * or / which in turn have higher priority than + or - which in turn have higher priority than + or -

6
6 Arithmetic Expressions and Trees ( x – a ) / b / - b ax Infix:( ( x – a ) / b ) Postfix:x a – b / Prefix:/ – x a b / stands for division operator, with higher precedence than, say, –

7
7 Arithmetic Expressions and Trees a ^ ( b – c ) / d / ^ d -a Infix:( ( a ^ ( b – c ) ) / d ) Postfix:a b c - ^ d / Prefix:/ ^ a – b c d Wrong: a ^ ( ( b – c ) / d ) bc

8
8 Data Structure to Traverse Trees Implement tree in C++ and traverse to print Implement tree in C++ and traverse to print To do so, define a NodeType data structure To do so, define a NodeType data structure Thus, a node must have operand-operator information (classification), and 1 or 2 subtrees Thus, a node must have operand-operator information (classification), and 1 or 2 subtrees For practical purposes, distinguish literals from variables (i.e. symbolic names) For practical purposes, distinguish literals from variables (i.e. symbolic names) Represent an arithmetic expression as a binary tree of such nodes with operators and operands Represent an arithmetic expression as a binary tree of such nodes with operators and operands And define functions that traverse the tree and prints operands and operators in the right order And define functions that traverse the tree and prints operands and operators in the right order

9
9 Tree Data Structure // node has class: literal, identifier, or operator. // Parenthesized expressions are reduced in tree: no ( ) typedef enum { Literal, Identifier, Operator } NodeClass; typedef struct NodeType * NodePtr; // forward // actual node structure; using the forward pointers typedef struct NodeType { NodeClass Class; // 3 classes, not C++ “class” NodeClass Class; // 3 classes, not C++ “class” char Symbol; // stores ident or small literal char Symbol; // stores ident or small literal int LitVal; // if Class == Literal: its value int LitVal; // if Class == Literal: its value NodePtr Left; // left subtree NodePtr Left; // left subtree NodePtr Right; // right subtree NodePtr Right; // right subtree } s_node_tp;

10
10 Make a New Node // malloc() new node from heap. Return pointer to node NodePtr Make( NodeClass Class, char Symbol, int value, NodePtr Left, NodePtr Right ) NodePtr Left, NodePtr Right ) { // Make NodePtr Node = (NodePtr)malloc( sizeof( struct NodeType ) ); if( Node ) { // is node’s space is really there? Node->Class = Class; Node->Symbol = Symbol; Node->LitVal = value; Node->Left = Left; Node->Right = Right; }else{ tree_error( ”No heap space for node”, Class ); } //end if return Node; } //end Make

11
11 Make a New Node // Example: for a * 8 we create the following tree... Node_ptr left = Make( Identifier, ‘a’, 0, NULL, NULL ); Node_ptr right = Make( Literal, ‘8’, 8, NULL, NULL ); Node_ptr root = Make( Operator, ‘*’, 0, left, right ); return root; } //end building tree

12
12 Copy Tree // recursively copy tree pointed to by Root. // Pass pointer to the copy to its caller NodePtr Copy( NodePtr Root ) { // Copy if ( Root == NULL ) { return NULL; }else{ return Make( Root->Class, Root->Symbol, Root->LitVal, Copy( Root->Left ), Copy( Root->Right ) ); } //end if } //end Copy

13
13 Print, Infix, Without Parentheses // Print in infix notation without parentheses ( ) void Print_No_Paren( NodePtr Root ) { // Print_No_Paren if ( Root ) { Print_No_Paren ( Root->Left ); if ( Root->Class == Literal ) { printf( "%d", Root->LitVal ); }else{ printf( "%c", Root->Symbol ); } //end if Print_No_Paren ( Root->Right ); } //end if } //end Print_No_Paren Input: ( a + x ) / b prints as: a + x / b misleading

14
14 Print, Infix, With Parentheses // Print in infix notation with parentheses ( and ) // though prints too many ( ) pairs void Print_Infix( NodePtr Root ) { // Print_Infix if ( Root ) { if ( Root->Class == Operator ) printf( "(" ); Print_Infix( Root->Left ); if ( Root->Class == Literal ) { printf( "%d", Root->LitVal ); }else{ printf( "%c", Root->Symbol ); } //end if Print_Infix( Root->Right ); if ( Root->Class == Operator ) printf( ")" ); } //end if } //end Print_Infix Input: ( a + x ) / b prints as: ( ( a + x ) / b ) -- OK

15
15 Postfix Without Parentheses // Print in Polish Postfix notation, no parentheses void Print_Postfix( NodePtr Root ) { // Print_Postfix if ( Root ) { Print_Postfix( Root->Left ); Print_Postfix( Root->Right ); if ( Root->Class == Literal ) { printf( "%d", Root->LitVal ); }else{ printf( "%c", Root->Symbol ); } //end if } //end Print_Postfix Input: a ^ ( b – c ) / d prints as: a b c - ^ d / -- OK

16
16 Prefix Without Parentheses // Prefix: operator executes when 2 operands found void Print_Prefix( NodePtr Root ) { // Print_Prefix if ( Root ) { if ( Root->Class == Literal ) { printf( "%d", Root->LitVal ); }else{ printf( "%c", Root->Symbol ); } //end if Print_Prefix ( Root->Left ); Print_Prefix ( Root->Right ); } //end if } //end Print_Prefix Input: ( a + x ) / b prints as: / + a x b -- OK

17
17 Interesting Examples Input 1:a + b * c ^ ( x – 2 * d ) / ( e – f ) Infix:( a + ( ( b * ( c ^ ( x – ( 2 * d ) ) ) ) / ( e – f ) ) ) Postfix:a b c x 2 d * - ^ * e f - / + Prefix:+ a / * b ^ c – x * 2 d – e f Input 2:4 / x ^ ( k – l / m ) * 8 * x - & 9 + n Infix:( ( ( ( ( 4 / ( x ^ ( k - ( l / m ) ) ) ) * 8 ) * x ) - ( & 9 ) ) + n ) Postfix:4 x k l m / - ^ / 8 * x * 9 & - n + Prefix:+ - * * / 4 ^ x – k / l m 8 x & 9 n

18
18 Use of Postfix Postfix, AKA Polish Postfix notation is a natural for code generation, not just for stack machines Postfix, AKA Polish Postfix notation is a natural for code generation, not just for stack machines Operands are needed first: Two for dyadic, or one for monadic operations Operands are needed first: Two for dyadic, or one for monadic operations Once generated and available on stack, stack machine can execute the next operation Once generated and available on stack, stack machine can execute the next operation Easy for compiler writer, natural for stack machine Easy for compiler writer, natural for stack machine Stack poor for execution, as all references are through memory: top of stack Stack poor for execution, as all references are through memory: top of stack Even a GPR architecture needs both operands available somewhere (in regs) to execute operator Even a GPR architecture needs both operands available somewhere (in regs) to execute operator

19
19 References Łukasiewicz: Łukasiewicz:

Similar presentations

© 2017 SlidePlayer.com Inc.

All rights reserved.

Ads by Google