Transcript Document
Recursive Data Structures and
Grammars
Themes
Recursive Description of Data Structures
Recursive Definitions of Properties of Data Structures
Recursive Algorithms for Manipulating and Traversing
Data Structures
Structural induction
Examples
Lists
Trees
Expressions and Expression Trees
List Processing
Recursive Definition
List := nil | (cons All List)
List<Type> := nil (cons Type List<Type>)
Process lists using these two cases and use
recursion to recursively process lists in cons
Use first and rest to access components of cons
Size is the number of conses (generally
number of constructors)
Prove properties by inducting on size – assume
2
property holds for smaller size objects and
Member
(defun member (x l)
(cond
((equal l nil) nil)
((equal x (first l)) t)
((member x (rest l)))))
3
Append
(defun append (x y)
(if (equal x nil)
y
(cons (first x) (append (rest x) y))))
Properties
1.
2.
3.
(append x nil) = x
(length (append x y)) = (+ (length x) (length y))
(append x (append y z)) = (append (append x y) z)
4
Structural Induction
When using induction on recursively defined data
structures like lists you can induct on the size of the data
structure = to the number of calls to the constructors.
When trying to show a property for a data structure of a
given size, you can assume that the property holds when
making a recursive call on a smaller data structure. You
must make sure that the property holds for all constructors
including base cases.
With lists (rest …) will return a smaller data structure (at
least one fewer cons)
Structural induction allows you to induct on the recursive
data structure without being explicit about the size
provided the IH is applied to smaller objects.
Proof of Property 1
Show (append x nil) = x using structural
induction
Base case. x = nil. In this case, (append nil
nil) returns nil = x.
By induction assume recursive call satisfies
the property [note (rest x) is smaller than x]
I.E. (append (rest x) nil) = (rest x)
Thus (append x nil) returns (cons (first x)
(rest x)) = x
Proof of Property 2
Show (length (append x y) = (+ (length x)
(length y)) using structural induction on x
Base case. x = nil. (append nil y) = y and
(length y) = (+ (length nil) (length y))
By induction assume recursive call satisfies the
property
(length (append (rest x) y) = (+ (length (rest x))
(length y))
Thus (length (append x y)) = (length (cons (first
x) (append (rest x) y)) = (+ 1 (length (rest x)) +
(length y)) = (+ (length x) (length y))
Proof of Property 3
Show (append x (append y z)) = (append
(append x y) z)
Base case. x = nil. (append nil (append y z)) =
(append y z) = (append (append nil y) z)
Assume property holds for (rest x)
(append (append x y) z)
(append (cons (first x) (append (rest x) y)) z) [by def]
(cons (first x) (append (append (rest x) y) z)) [by def]
(cons (first x) (append (rest x) (append y z))) [by IH]
(append (cons (first x) (rest x)) (append y z)) [by def]
(append x (append y z)) [by property of cons]
Reverse
(defun reverse (l)
(if (equal l nil)
nil
(append (reverse (rest l)) (cons (first l) nil))))
Properties
(length (reverse x)) = (length x)
(reverse (append x y)) = (append (reverse y) (reverse x))
(reverse (reverse x)) = x
9
Proof of Property 2
Show (rev (append x y)) = (append (rev y) (rev
x))
Base case. x = nil. (rev (append nil y)) = (rev y) =
(append (rev y) nil) = (append (rev y) (rev nil))
Assume property holds for (rest x)
(rev (append x y))
(rev (cons (first x) (append (rest x) y)) [def apppend]
(append (rev (append (rest x) y)) (cons (first x) nil)) [def rev]
(append (append (rev y) (rev (rest x))) (cons (first x) nil)) [IH]
(append (rev y) (append (rev (rest x)) (cons (first x) nil))) [prop app]
(append (rev y) (rev x)) [def of rev]
Proof of Property 3
Show (rev (rev x)) = x
Base case. x = nil. (rev (rev nil)) = (rev nil) = nil
Assume property holds for (rest x)
(rev (rev x))
(rev (append (rev (rest x)) (cons (first x) nil))) [def rev]
(append (rev (cons (first x) nil)) (rev (rev (rest x))))
[property 2 of rev]
(append (cons (first x) nil) (rev (rev (rest x)))) [def of
rev]
(append (cons (first x) nil) (rest x)) [IH]
(cons (first x) (append nil (rest x))) [def of app]
(cons (first x) (rest x)) = x [def of app and prop of cons]
n-Trees
Finite collection of nodes
Each node has exactly one parent, but for the
root node
Each node may have up to n children
A leaf node has no children
An interior node is a node that is not a leaf
Each subtree is a tree rooted at a given node
Tree := nil | (All List<Tree>)
E.G. (1 ((2 nil) (3 nil) (4 nil)))
Binary Trees
A binary tree is a 2-tree
A binary tree is
Empty, or
Consists of a node with 3 attributes:
value
left, which is a binary tree
right, which is a binary tree
• BinTree<Type> := (Type BinTree<Type> BinTree<Type>)
E.G. (1 (2 nil nil) (3 (4 nil nil) (5 nil nil)))
(BinTree 1 (BinTree 2 nil nil)
(BinTree 3 (BinTree 4 nil nil) (BinTree 5 nil nil)))
Number of Nodes of a Binary
Trees
Nnodes(T) = 0 if T is empty
Nnodes(T.left) + Nnodes(T.right) + 1
(defun Nnodes (BT)
(if (equal BT nil)
0
(+ (Nnodes (left BT)) (Nnodes (right BT)) 1)))
(defun left (BT) (second BT)) (defun right (BT) (third BT))
Height of Binary Trees
Height of tree T, H(T), is the max length of
the paths from the root all of the leaves
H(T) = -1 if T is empty
max( H(left(T)), H(right(T)) ) + 1
(defun Height (BT)
(if (equal BT nil)
-1
(+ (max (Height (left BT)) (Height (right BT))) 1)))
Correctness of Height
Show (Height BT) = length of the longest
path in BT
Prove by structural induction
Base case. -1 for nil is needed to obtain the correct
height of a tree with a single node.
Assume (Height (left BT)) and (Height (right BT))
compute the lengths of the longest paths in the left and
right subtrees
The longest path in BT is one more than the longest
path in either the left or right subtrees which by
induction is one more than the maximum of (Height
(left BT)) and (Height (right BT))
Internal Path Length (IPL)
The sum of the length of the paths from the
root to every node in the tree
Recursively:
IPL( T ) = 0 if T is empty
IPL( T ) = IPL( left( T )) + IPL( right( T )) +
num_nodes( T ) – 1
(defun IPL (BT)
(if (equal BT nil)
0
(+ (IPL (left BT)) (IPL (right BT)) (- (Nnodes BT) 1))))
IPL Verification
(check= (IPL nil) 0)
(check= (let ((BT (consBinTree 1 (consBinTree 2 nil nil)
(consBinTree 3 (consBinTree 4 nil nil)
(consBinTree 5 nil nil))))) (IPL BT)) 6)
1
IPL = 6 = 0 + 2 + 4
3
2
4
5
Nnodes = 5
IPL((left BT)) = 0
IPL((right BT)) = 2
Correctness of IPL
Show (ipl BT) = sum of the lengths of the
paths from the root to all nodes in the tree.
Prove by structural induction
Base case. 0 is needed to get the proper value for a tree
with a single node.
Assume (ipl (left BT)) and (ipl (right BT)) compute the
sum of the lengths of paths in the left and right subtrees
The length of each path in BT is one more than the
lengths of the paths in the left and right subtrees. Thus
one has to be added for each node in the left and right
subtrees and since there are (- (Nnodes BT) 1) such
nodes this must be added to the sum of (ipl (left BT))
and (ipl (right BT))
Recurrence for the Number of
Binary Trees
Let Tn be the number of binary trees with n
nodes.
T0 = 1, T1 = 1, T2 = 2, T3 = 5
n
1
T
TT
n
k
0
k
n
k
1
Expression Trees
Basic arithmetic expressions can be
represented by a binary tree
Internal nodes are operators
Leaf nodes are operands
Consider 2 * ( 3 + 5 ) :
*
2
+
3
5
Expression Tree Definition
ExpTree :=
(Number Integer) |
(Add ExprTree ExprTree) |
(Mult ExprTree ExprTree)
(defun NumNode (val) (list 'Number val))
(defun AddNode (E1 E2) (list 'Add E1 E2))
(defun MultNode (E1 E2) (list 'Mult E1 E2))
(MultNode (NumNode 2)
(AddNode (NumNode 3) (NumNode 5)))
Expression Tree Evaluation
Check each case in the recursive definition,
recursively evaluate subexpressions and
apply appropriate operator
(defun EvalExpr (E)
(cond
((isNumber E) (Val E))
((isAdd E) (+ (EvalExpr (Op1 E)) (EvalExpr (Op2 E))))
((isMult E) (* (EvalExpr (Op1 E)) (EvalExpr (Op2 E))))))
(check= (let ((E (MultNode (NumNode 2)
(AddNode (NumNode 3) (NumNode 5)))))
(EvalExpr E)) 16)
Expression Trees with Variables
What if we allow variables in expression
trees?
The value depends on the values of the
variables
Consider x * ( z + 5 )
When x = 2 & z = 5 the value is 20
When x = 0 & z =5 the value is 0
When x = 2 & z = -1the value is 8 x
…
*
+
z
5
Environments
Need to look up the values of all variables
occurring in the expression
Environment contains a list of bindings
where a binding is a pair (name value) that
binds a value to the name of the variable
E.G. env = ((x 2) (z 5))
lookup returns the value associated with a
given variable in an environment
(lookup ‘x env) 2
Expression Tree Evaluation
Modify EvalExpr to include variables –
need second argument containing an
environment and must handle variable case
(defun EvalExpr (E env)
(cond
((isNumber E) (Val E))
((isVariable E) (lookup E env))
((isAdd E) (+ (EvalExpr (Op1 E) env) (EvalExpr (Op2 E) env)))
((isMult E) (* (EvalExpr (Op1 E) env) (EvalExpr (Op2 E) env)))))
Binary Search Trees
Binary Search Tree (BST)
Binary Tree
All elements in left(T) are < value(T)
All elements in right(T) are value(T)
Each subtree of a BST is a BST
Partially Ordered Trees
Heap (binary)
Complete binary tree
So, height = Θ(lg n)
Nodes are assigned some measure, a priority
No node has lower priority than its children
Inorder traversal
Recursively visit nodes in T.left
visit root
Recursively visit nodes in T.right
An in order traversal of a BST lists the
elements in sorted order. Proof by
induction.
Expression Trees
Basic arithmetic expressions can be
represented by a binary tree
Internal nodes are operators
Leaf nodes are operands
Consider 2 * ( 3 + 5 ) :
Note that parentheses don’t
appear. Expression trees are
not ambiguous, as infix
expressions are (can be).
*
2
+
3
5
Expression Tree – In-order Traversal
An in-order traversal yields
2*3+5
We put parentheses around
every operation to make
this correct: (2 * ( 3 + 5 ) )
(not all are needed)
*
2
+
3
5
Pre- and Post-Order Traversal
Always go left-right
Pre (me first):
Visit node
Traverse left subtree
Traverse right subtree
Post (me last):
Traverse left subtree
Traverse right subtree
Visit node
Expression Trees – Pre- and PostOrder
Pre: * 2 + 3 5
Post: 2 3 5 + *
Note: Parentheses
never needed
*
2
+
3
5