The following classes were defined in class:
public void print() {
LLNode<T> listptr = head;
while (listptr != null) {
System.out.print(listptr.getElement() + " ");
listptr = listptr.getNext();
}
System.out.println();
}
You can type this method into the LinkedList class to help you test your code.
Try to write the following method using the iterative style:
public T last
returns the last element of the linked list.
For example, we can create a toString method that creates a String representation of the linked list by adding the following method to LinkedList:
public String toString() {
if (head == null)
return null;
return head.toString();
}
and the following method to LLNode:
public String toString() {
if (getNext() != null)
return getElement().toString() + " " + getNext().toString();
else
return getElement().toString();
}
Try entering this code into the classes and testing it.
Now your turn. Try to write the method:
T recursiveLast()
that returns the last element of the list but uses structural recursion.
For example, the usual example is the factorial method that takes an int n and returns the product of 1*2*3*...*n.
public static int factorial(int n) {
if (n == 0)
return 1;
else
return n * factorial(n - 1);
}
Notice that factorial calls itself on a reduced input each time until we get to the
stopping condition (n = 0).
Here is the start of a method that returns the length of a linked list.
public int length() {
return length(head);
}
public int length(LLNode<T> node) {
if (node == null)
return a base value
else
return processing and call length(node.getNext());
}
Place this code into LinkedList.java and add the necessary expressions to complete the code.
Now try this one. The method append will take a LinkedList and append the LinkedList to the end of the current list. However, it will do this recursively. (You probably notice that this is not the most efficient way to write append, but try it anyway. It is a good exercise in the technique.)
public void append(LinkedList<T> list) {
head = append(this.head, list.head);
}
public LLNode<T> append(LLNode<T> list1, LLNode<T> list2) {
if (list1 == null)
return a base value
else
return processing and call append(reduced list1, list2)
public void merge(LinkedList<T> list) {
For example, suppose list1 is {2 4 6 8} and
list2 is {1 3 5}, the the result of calling
list1.merge(list2) should be to have list1 be {1 2 3 4 5 6 8}.
It is ok to destroy list2 in the process.
What you must not do: Do not just run through the parameter list calling removeFromHead to get the next element and insertInOrder to place it into the list. While this method works, it is quite inefficient and you will notice a large slowdown on long (100,000+) lists.
What you should do: Make your method repeatedly check the first element of each list, until there are no more elements (actually you can stop a little sooner) and make the smaller of the two elements be the next element of the final list. This is a challenging task, and you can use any of the three styles described above.
At the end of lab, email your code to me.