Version: 0.3.38

Recursion#

Module:

Recursion

Git Repository:

Lab 03—Recursions

Objectives:
  • Play with the concept of recursion

  • Implement a linked list in Java

Simple Recursions#

We start this lab session with a few small recursive algorithms. Each of them can be written either using iteration of recursion, but we focus here on recursive solutions.

Exercise

Write a program that raises a given value \(v\) to a given positive exponent \(e\). Formally, the task is to write a function \(\mathit{power}(v, e) = v^e\).

  1. Identify the base and the recursive cases.

  2. Look at the file WarmUp.java, and complete the method named power, using recursion.

  3. You can use the PowerTest.java to test your solution.

Exercise

Write a program that sums up all the values contained in the given array. Use recursion.

  1. Identify the base and the recursive cases.

  2. Look at the file WarmUp.java, and complete the method named sum, using recursion.

  3. You can use the ArraySumTest.java to test your solution.

Exercise

We now turn to palindromes, that is, words that are symmetrical such as “kayak”, “madam” or “level”. Write a recursive procedure that checks if a given word is indeed a palindrome.

  1. Identify the base and the recursive cases.

  2. Look at the file WarmUp.java, and complete the method named isPalindrome, using recursion.

  3. You can use the PalindromeTest.java to test your solution.

Exercise

Write a recursive procedure that converts a given number into a different base. The base of a number denotes the number of symbols used. For instance, in base 2, we only use two symbols \(\{0,1\}\), and for instance 10 (in base 10) is written ’1010’. Similarly, 5 in base 10 becomes ’12’ in base 3. We can verify that \((1 \times 3^1) + (2 \times 3^0) = 5\).

  1. Identify the base and the recursive cases.

  2. Look at the file WarmUp.java, and complete the method named toBase, using recursion.

  3. You can use the BaseConversionTest.java to test your solution.

Linked Lists#

We continue by implementing the sequence ADT as a singly linked list. We implemented the same sequence ADT using arrays in Lecture 2.2.

public abstract class Sequence<T> {
    int length();
    T get(int index) throws InvalidIndex;
    void set(int index, T item) throws InvalidIndex;
    void insert(int index, T item) throws InvalidIndex;
    void remove(int index) throws InvalidIndex;
    int search(T item);
    boolean isEmpty();
}

In this lab session, we will contrast two implementations: One using iteration, and one using recursion.

Using Iteration#

We start with the iterative implementation, which is often more “natural”. Figure 1 shows one way to implement the Sequence. The IterativeList class may contain a Node, which, in turn, may refer to another Node, and so on and so forth. The list is thus formed by “linked” nodes. You will find this design in IterativeList.java.

../_images/lab_recursion.svg

Fig. 2 The IterativeList implements the Sequence ADT and uses the INode class.#

Exercise

Implement the insert method using a loop. As we saw during the lectures, you will the getNode method, that finds the ith node.

  1. Implement the getNode method.

  2. Implement the insert method.

  3. The test cases from IterativeListTest.java can help you find issues in your algorithm.

Exercise

In the worst case, how many comparisons does your algorithm requires? What is the order of growth? Argue.

  1. What is the worst case scenario for the insertion?

  2. How many comparisons take place in the worst case (a frequency table may help you).

  3. Argue for an order of growth

Exercise

In the worst case, how much memory does your solution requires?

Using Recursion#

We will now use recursion to implement the same linked list. Look at the file RecursiveList.java. The length method is a simple example, shown below:

@Override
public int length() {
    return lengthFrom(head);
}

private int lengthFrom(RNode<T> start) {
    if (start == null)
        return 0;
    return 1 + lengthFrom(start.next);
}

Often, recursive algorithms need to accept more arguments than their iterative counterpart. That’s the role of the lengthFrom operation, which embodies the actual recursive implementation. The length operation directly calls it.

Exercise

By taking inspiration on the length method, implement the insert operation in a recursive manner. Here are questions that might help to guide you.

  1. Can you identify self-similar sub problems. The structure of the linked list may help you.

  2. What are the base cases?

  3. What are the recursive cases?

Exercise

In worst case, how many comparisons will your recursive insertion takes?

  1. Identify the worst case. What is it?

  2. Count the comparisons needed for each base and recursive cases.

  3. Write down the number of comparisons as a recurrence relationship.

  4. Solve this recurrence.

Exercise

In the worst case, how much memory will it takes? Remember to account for the call stack.

Benchmark#

Let see now is theory matches practice. To get some concrete evidence, we will try to insert items in both an IterativeList and in a RecursiveList. Take a look at the file Benchmark.java, which implements the above scenario.

Exercise

Run the benchmark on your machine. What result do you get. To run the benchmark, you can use the command:

$ java -cp target/lab03-0.1-SNAPSHOT.jar \
           no.ntnu.idata2302.lab03.Benchmark

Exercise

Why do you think happen to RecursiveList? Why is it underperforming?