Recursive Linked Lists
Recursive Linked Lists
An alternative way to define a linked list is to do so recursively . This is the approach taken by some programming languages, such as Lisp and Scheme. It can also be done in C++ or Java.
In this view, a list can be defined as follows.
definition A list is either
a. an empty list, containing no data items, or
b. a first data item followed by a list containing the rest of its data items.
For example, in a list written
( x y z w )
first is x, and rest is ( y z w ).
A class definition for a list defined in this way might start like this:
class RecursiveList implements List {
Object first;
RecursiveList rest;
.
.
.
Note that RecursiveList is defined recursively; that is, the definition contains a reference to the thing being defined. That's frowned upon in English, but it is a powerful tool used by mathematicians and computer scientists.
This definition lends itself to writing list operations as recursive functions.
example Write a method for RecursiveList which counts the number of elements in the list.
int size() {
if ( isEmpty() )
return 0;
else
return 1 + rest.size();
}
example Write a method to print the contents of a RecursiveList.
void display(){
if( !isEmpty() ){
System.out.println(first.toString());
rest.display();
}
}
Q: In what order will the items be displayed? Would it be possible to display them in the reverse order?
example Suppose that a RecursiveList is being used to hold a list of Integers. Write a method which finds the sum of the elements in the list.
example Given a list of strings, and a particular string to search for, search the list for occurrences of the string. Return a count of the number of occurrences found.
Implementation
How can a recursively defined linked list be implemented in Java?We start by defining a class with two instance variables:
class RecursiveList {
Object first;
RecursiveList rest;
Add get and set methods for first and rest:
public Object getFirst(){ return first; }, etc.
When we write constructors for the list class, we have to decide some implementation details: What does an empty list look like? What does a list with one element look like? In general, what is the physical structure of a valid linked list? We can answer these questions as follows:
- The empty list is represented by a node whose first and rest are both null.
- In a list with one element, "rest" should be an empty list.
- In a list with n elements, "rest" should be a list of (n-1) elements.
- A list with n data items is represented by a linked list of n+1 nodes. The first n nodes contain the n data items as their "first"s. In the (n+1)-th node, both first and rest are null.
So we can write the following constructors:
RecursiveList() { // initializes an empty list
first = rest = null;
}
RecursiveList(Object item){ // initializes a list with one element
first = item;
rest = new RecursiveList();
}
RecursiveList(Object item, RecursiveList rest){ // initializes a list with a given first element and rest-of list
first = item;
this.rest = rest;
}
It is possible to implement any list operation with these basic ones. However, it is also useful to define a few additional operations
private void prepend(Object item){
rest = new RecursiveList(first,rest);
first = item;
}
private Object removeFirst(){
if(isEmpty())
return null;
else {
Object temp = first;
first = rest.first;
rest = rest.rest;
return temp;
}
}
We can then implement the methods of the list interface. Here are a few examples:
public boolean add(Object item){
if(isEmpty())
prepend(item);
else
rest.add(item);
return true;
}
public Object get(int index){
if(isEmpty())
throw new ArrayIndexOutOfBoundsException();
else if(index==0)
return first;
else
return rest.get(index-1);
}
public Object remove(int index){
if(isEmpty())
throw new ArrayIndexOutOfBoundsException();
else if(index==0)
return removeFirst();
else
return rest.remove(index-1);
}
public void add(int index, Object item){
if(index==0)
prepend(item);
else if(isEmpty())
throw new ArrayIndexOutOfBoundsException();
else
rest.add(index-1, item);
}