The following are some notes taken during a lecture.
Recursively Defined Functions
Definition: A recursive or inductive definition of a function consists of two steps.
- BASIS STEP: Specify the value of the function at zero.
- RECURSIVE STEP: Give a rule for finding its value at an integer from its values at smaller integers.
A function f(n) is the same as a sequence a0, a1, … , where f(i) = ai.
Example: Suppose f is defined by:
f(0) = 3,
f(n + 1) = 2f(n) + 3
Find f(1), f(2), f(3), f(4)
Solution:
f(1) = 2f(0) + 3 = 2∙3 + 3 = 9
f(2) = 2f(1)+ 3 = 2∙9 + 3 = 21
f(3) = 2f(2) + 3 = 2∙21 + 3 = 45
f(4) = 2f(3) + 3 = 2∙45 + 3 = 93
Example: Give a recursive definition of the factorial function n!:
Solution:
f(0) = 1
f(n + 1) = (n + 1)∙ f(n)
Fibonacci Numbers
Recursively Defined Sets and Structures
Recursive definitions of sets have two parts:
- The basis step specifies an initial collection of elements.
- The recursive step gives the rules for forming new elements in the set from those already known to be in the set.
Sometimes the recursive definition has an exclusion rule, which specifies that the set contains nothing other than those elements specified in the basis step and generated by applications of the rules in the recursive step.
We will always assume that the exclusion rule holds, even if it is not explicitly mentioned.
Example: Subset of Integers S:
BASIS STEP: 3 ∊ S.
RECURSIVE STEP: If x ∊ S and y ∊ S, then x + y is in S.
Initially 3 is in S, then 3 + 3 = 6, then 3 + 6 = 9, etc.
Example: The natural numbers N.
BASIS STEP: 0 ∊ N.
RECURSIVE STEP: If n is in N, then n + 1 is in N.
Initially 0 is in S, then 0 + 1 = 1, then 1 + 1 = 2, etc.
Recursively Defined Strings
Definition: The set Σ* of strings over the alphabet Σ:
BASIS STEP: λ ∊ Σ* (λ is the empty string)
RECURSIVE STEP: If w is in Σ* and x is in Σ, then wx ∈ Σ*.
Example: If Σ = {0,1}, the strings in Σ* are the set of all bit strings, λ,0,1, 00,01,10, 11, etc.
Example: If Σ = {a,b}, show that aab is in Σ*.
- Since λ ∊ Σ* and a ∊ Σ, a ∊ Σ*.
- Since a ∊ Σ* and a ∊ Σ, aa ∊ Σ*.
- Since aa ∊ Σ* and b ∊ Σ, aab ∊ Σ*.
String Concatenation
Definition: Two strings can be combined via the operation of concatenation. Let Σ be a set of symbols and Σ* be the set of strings formed from the symbols in Σ. We can define the concatenation of two strings, denoted by ∙, recursively as follows.
BASIS STEP: If w ∈ Σ*, then w ∙ λ= w.
RECURSIVE STEP: If w1 ∈ Σ* and w2 ∈ Σ* and x ∈ Σ, then w1 ∙ (w2 x)= (w1 ∙ w2)x.
Often w1 ∙ w2 is written as w1 w2.
If w1 = abra and w2 = cadabra, the concatenation w1 w2 = abracadabra.
String Length
Example: Give a recursive definition of l(w), the length of the string w.
Solution: The length of a string can be recursively defined by:
l(λ) = 0;
l(wx) = l(w) + 1 if w ∊ Σ* and x ∊ Σ.
Balanced Parenthesis
Example: Give a recursive definition of the set of balanced parentheses P.
Solution:
BASIS STEP: () ∊ P
RECURSIVE STEP: If w ∊ P, then () w ∊ P, (w) ∊ P and w () ∊ P.
Show that (() ()) is in P.
Why is ))(() not in P?
Well Formed Formulae in Propositional Logic
Definition: The set of well-formed formulae in propositional logic involving T, F, propositional variables, and operators from the set {¬,∧,∨,→,↔}.
BASIS STEP: T,F, and s, where s is a propositional variable, are well-formed formulae.
RECURSIVE STEP: If E and F are well formed formulae, then (¬ E), (E ∧ F), (E ∨ F), (E → F), (E ↔ F), are well-formed formulae.
Examples: ((p ∨q) → (q ∧ F)) is a well-formed formula.
pq ∧ is not a well formed formula.
Rooted Trees
Definition: The set of rooted trees, where a rooted tree consists of a set of vertices containing a distinguished vertex called the root, and edges connecting these vertices, can be defined recursively by these steps:
BASIS STEP: A single vertex r is a rooted tree.
RECURSIVE STEP: Suppose that T1, T2, …,Tn are disjoint rooted trees with roots r1, r2,…,rn, respectively. Then the graph formed by starting with a root r, which is not in any of the rooted trees T1, T2, …,Tn, and adding an edge from r to each of the vertices r1, r2,…,rn, is also a rooted tree.
Full Binary Trees
Definition: The set of full binary trees can be defined recursively by these steps.
BASIS STEP: There is a full binary tree consisting of only a single vertex r.
RECURSIVE STEP: If T1 and T2 are disjoint full binary trees, there is a full binary tree, denoted by T1∙T2, consisting of a root r together with edges connecting the root to each of the roots of the left subtree T1 and the right subtree T2.
Youtube
Recursive Definition for Factorials
Base Case: F(0) = 1
Recursive: F(n) = n * F(n-1), where n > 0
Recursive Algorithms
Definition: An algorithm is called recusive if it solves a problem by reducing it to an instance of the smae problem with smaller input. For it to terminate the instance of the problem must eventually be reduced to some initial case for which the solution is known.
Example:
Compute n! (factorial)
Solution:
procedure F(n) // n is non-negative
if n == 0 then return 1 // base case
else return F(n-1) // recursive step
{output is n!}
Example:
Compute a^n where a is nonzero real number and n is nonnegative integer
Solution:
pocedure: power(a, n) // where a is nonzero real number, n is nonegative integer
if n == 0 return 1
else return a * power(a, n-1)
{output is a^n}
Recursive Greatest Common Divider (GCD Algorithim)
Example:
Compute GCD of two nonnegative integers a and b with a < b
Solution:
use reduction
GCD(a,b) = GCD(b mod a, a) and the condition GCD(0,b) = b when b > 0
procedure GCD(a,b) // a < b)
if a == 0 return b
else return GCD(b mod a, a)
Recursive Modular exponentiation Algorithm
Example:
Compute b^n mod m, where b,n,m are integers with m>=2, n>=0, 1<=b<=m
Solution:
Recursive Binary Search Algorithm
Correctness of Recursive Algorithms
Both mathematical and strong induction are useful techniques to show that recursive algorithms always produce the correct output.
Example:
Prove that the algorithm for computing the powers of real numbers is correct
procedure: power(a,n) // a nonzero real, n nonnegative integer)
if n == 0 return 1
else return a * power(a, n-1)
Solution:
Use mathematical induction on the exponent n.
BASIS STEP: a^0 = 1 for every nonzero real number a, and power(a,0) = 1
INDUCTIVE STEP: The inductive hypothesis is that power(a,k) = a^k, for all a != 0. Assuming the inductive hypothesis, the algorithm correctly computes a^k+1, since: power(a,k+1) = a * power(a,k) = a * a^k = a^k+1
Recursive Merge Sort
- Merge Sort iteratively splits list (with even number of elements)
- Each sublist is represented by balanced binary tree
- At each step a pair of sublists is successively merged into a list with elements increasing order
- Succession of merged lists is represented as binary tree
Complexity of Merge Sort
The number of comparisons to merge list with n elements is O(n log n)
- For simplicity assume that n is power of 2, say 2^m
- At the end of splitting process, we have a binary tree with m levels and 2^m lists with one element at level m
- The merging process begins at level m with the pairs of 2^m lists with one element combined into 2^m-1 lists of two elements
- The procedure continues, at each level
- The merger takes at most 2^m-k + 2^m-k – 1 = 2^m-k+1 – 1
- Youtube this if needed
eof