CSE 40872 Lecture 014

Topic:Recursion (Backtracking)
Author: Peter Bui <pbui@cse.nd.edu>
Date: October 5, 2009

Recursion

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)

Components

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)

Usage

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

Structure

// 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);
}

Stacks

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]);
        }
    }
}

Backtracking

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

Backtracking Structure

Summary

Recursion is good for when you can divide the problem into smaller pieces that resemble the original problem. The structure is relatively simple: