Title: Recursion NonLinear Data
1- Recursion Non-Linear Data
2More inductive structures
- Consider an arithmetic expression 345
- How do we generalize this?
- numnumnum will describe it for any three
numbers - But this will not handle 3457
- So we say, an expression is
- A number
- A sum of two expressions
- A product of two expressions
- Observe that this is an inductive/recursive defn.
3Expressions
- We write
- Expr ? Num
- Expr ? Expr Expr
- Expr ? Expr Expr
- Each line is a rule defining Expr.
- Each rule provides an alternative for Expr.
- Some rules are recursive.
- How do we model expression data in C?
- The Expr has three variants i.e. is a union of
three types. - Expr Num ? SumExpr ? ProdExpr
4Type Definitions
- Alternatives can be modeled as unions (first
attempt)
typedef union int ne SumExpr se ProdExpr
pe Expr
typedef struct Expr lt Expr rt SumExpr
typedef struct Expr lt Expr rt ProdExpr
5Type Definitions
- Expr uses SumExpr and vice-versa.
- Easy to fix Use dummy declarations
- union __expr
- typedef union __expr Expr
- Now we can use Expr to define SumExpr and
ProdExpr. - Then we can use these in the defintion of Expr.
- Also, when we pass structures around as
parameters, they are copied. To avoid this we
define Expr as pointer type.
6Type Definitions
/ file expr.h /
union __expr typedef union __expr Expr
typedef struct Expr lt Expr rt SumExpr
typedef struct Expr lt Expr rt ProdExpr
union __expr int ne SumExpr se ProdExpr pe
7Type Definitions
- Given a declaration
- Expr e
- what is e? a number, a sum or a product?
- How we can keep track?
- Use tagged union
8Expressions
- Two issues
- SumExpr and ProdExpr are defined in terms of Expr
- We need to keep track of which variant an Expr.
- Solutions
- Use recursive types with forward (dummy)
declarations in C. - Use Tagged unions i.e.
- if T T1 ?? T2 ? T3
- we redefine
- T Tag x (T1 ? T2 ? T3)
- where Tag typename1, typename2,
typename3
9Type Definitions
/ file expr.h /
struct __expr typedef struct __expr Expr
typedef struct Expr lt Expr rt SumExpr
typedef struct Expr lt Expr rt ProdExpr
10Type Definitions
/ file expr.h /
typedef enum INT0 SUM1 PROD2 ExprType
struct __expr ExprType eTag union int
ne SumExpr se ProdExpr pe eVar
11Expression Evaluation
- Define an evaluator for expressions
- int eval(Expr e)
- What should be the behavior of this operation?
- If e is an INT, then return the integer
- If e is a SUM, then evaluate the left and right
components, and add the results. - If e is a PROD, then evaluate the left and right
components, and multiply the results.
12Expression Evaluation
int eval(Expr e) if (e-gteTag INT) else
if (e-gteTag SUM) else
return e-gteVar-gtne
return eval(e-gteVar.se-gtlt)
eval(e-gteVar.se-gtrt)
return eval(e-gteVar.pe-gtlt)
eval(e-gteVar.pe-gtrt)
//Can we write this using iteration?
13Nonlinear Data
- Can we generalize the Expr data type?
- Consider this structure
S ? B S ? S op1 S S ? S op2 S
The type definition would be
S Tag x (B ? S1 ? S2) Tag bType,
opType1, opType2 S1 S x S S2 S x S
14Nonlinear Data
We can further any-size the structure
S ? B1 B2 Bm S ? S op1 S S ? S op2
S S ? S opn S
And the types will have to be changed accordingly
S Tag x (B1 ? B2 ? Bm ? S1 ? S2 ? Sn)
Tag bT1, bT2 bTm, oT1, oT2, , oTn S1
S x S S2 S x S Sm S x S
15Nonlinear Data
- Can we avoid all these type definitions?
- We observe that there are two essential types of
data basic data (B1, B2, ) and structured
(recursive) data (S1, S2, ). - We club these together
- Then TerminalType can be defined independently as
a union of whatever types, if needed. - NonTerminalType can be defined as follows
S TerminalType ? NonTerminalType
NonTerminalType OpVal x S x S OpVal op1,
op2,
16Nonlinear Data Binary Trees
Nonlinear data can now be visualized as tree
structures
SumExpr U ProdExpr
SumExpr U ProdExpr
17Nonlinear Data Binary Trees
Nonlinear data can now be visualized as tree
structures
S3
S3
18Nonlinear Data - Binary Tree Type Definition
typedef struct BTree left BTree right
InteriorData dt Interior
struct __node typedef struct __node BTree
struct __node NodeType nt union
Leaf lf Interior in nd
typedef enum LF 1 NLF2 NodeType
// Define Leaf and InteriorData. Figure out the
order!
19General strategy / algorithm template for
operations on trees
Problem Perform (some) operation on all nodes of
the tree bt.
Value visit(BTree bt) if (bt-gtnt LF) return
visitLeaf(bt-gtnd.lf) else v1
visit(bt-gtnd.in-gtleft) v2
visit(bt-gtnd.in-gtright) return
visitNonLeaf(v1, v2, bt-gtnd.in-gtdt)
20// Assume the following type definitions typedef
int Leaf typedef enum PLUS1, STAR2
InteriorData typedef int Value
// The following functions will complete the
evaluator
Value visitLeaf(Leaf lf) return lf
Value visitNonLeaf(Value vl, Value vr,
InteriorData dt) if (dt PLUS) return vl
vr else if (dt STAR) return vl vr
// Create appropriate header and code files
21Nonlinear Data Trees
Nonlinear data can now be visualized as tree
structures
S3
S1
S1
S3
S3
22Nonlinear Data - Characteristics
- Linear data captures linear relations
position of each element fixed w.r.t neighbors - Non-linear data captures partial orders some
elements are related to some others some are not.
23Tree Characteristics
- There is a root node.
- Each node has a (finite) number of children.
- Nodes with no children are leaf nodes.
- Conversely, each node has (atmost one) parent
- Root node has no parent.
24Trees - Usage
- Trees can be used to model file systems (e.g.
Unix file system) - Root (i.e. / ) is the root of the tree
- Directories are non-leaf nodes
- Non-directories are leaf nodes.
- So what?
- All file system level operations can be modeled
using the visitor pattern - Examples (commands in Unix)
- find
- cp R