Topic: | Recursion (Backtracking) |
---|---|
Author: | Peter Bui <pbui@cse.nd.edu> |
Date: | October 5, 2009 |
Function or algorithm is defined in terms of itself; Any routine that calls itself is recursive:
Fib(n): Fib(0) is 0 Fib(1) is 1 Fib(n) is Fib(n - 1) + Fib(n - 2)
1. Base Case: Non-recursively defined values that limit or cut off recursion:
Fib(0) is 0 Fib(1) is 1
2. Recursive Step: Recursive definition or reapplication of function on new subset:
Fib(n) is Fib(n - 1) + Fib(n - 2)
Most useful for tasks that can be defined in terms of similar subtasks: sorting, searching, traversal.
def color_vertex(v, c):
if (v.color is None): # Recursive case
v.color = c
for n in v.neighbors:
if not color_vertex(n, c.opposite):
return false
return true
else if g.colors == c: # Base case
return true
else # Base case
return false
// Recursive traversal
static void dfs_r(Graph &g, int v = 0) {
if (!g.visited[v]) {
g.visited[v] = true;
for (size_t i = 0; i < g.edges[v].size(); i++)
dfs_r(g, g.edges[v][i]);
}
}
// Wrapper for recursive solution
static void dfs(Graph &g) {
memset(g.visited, 0, sizeof(int)*g.vertices);
dfs(g, 0);
}
Recursion can be emulated using stacks since it implicitly uses the program call stack.
static void dfs_s(Graph &g, int v = 0) {
stack<int> s;
s.push(v);
while (!s.empty()) {
v = s.top(); s.pop();
if (!g.visited[v]) {
g.visited[v] = true;
for (size_t i = 0; i < g.edges[v].size(); i++)
s.push(g.edges[v][i]);
}
}
}
Systematic method of iterating through all possible configurations of a search space (i.e. BRUTE FORCE).
def backtrack(s):
if is_solution(s):
process_solution(s)
else:
for c in construct_candidates():
if backtrack(c):
return
Recursion is good for when you can divide the problem into smaller pieces that resemble the original problem. The structure is relatively simple: