Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

1. Objectives This assignment will help you to: • Learn how to program using the

ID: 3596815 • Letter: 1

Question

1. Objectives

This assignment will help you to:

• Learn how to program using the linked list data structure

• Understand how recursive data structure works

• Learn how to write and use generic classes

2. Overview

You write a generic class named LinkedListRec that implements the singly linked list using recursions. The class must have the following methods. Use recursion to implement most of these methods based on the implementation requirements described in item 3 in this document.

• size, empty

• insertBefore, insertAfter

• addAtHead, addAtEnd

• remove – remove an item at a given index

• removeFront, removeEnd

• replace – replace the item at a given index by a new item

• peekFront, peekEnd

• toString

You must also write another class LinkedListRecTest that tests the implementation of your class LinkedListRec. LinkedListRecTest will use LinkedListRec class to create a collection of Strings or other objects and call each method in LinkedListRecTest to perform some operation.

3. Implementation Requirements

• The linked list LinkedListRec only has 1 data field: head. You cannot add additional data fields like size, tail, etc.

• You must write a generic class LinkedListRec.

• You must write your own LinkedListRec class. You cannot use the one provided in the Java API.

You must use recursion to implement the following methods. Each of these methods must have a public wrapper method and a private recursive counterpart method. For example, for method size, there is a public method size and a private recursive counterpart method size.

Note: because the main purpose of this assignment is recursion, if you don’t implement a method below using recursion, you will get 0 point for that method.

Note: the methods: size, toString were already implemented in the given LinkedListRec.java. These 2 methods will NOT be counted towards your grade.

o size

o toString

o addAtEnd

o insertBefore, insertAfter

o remove – remove an item at a given index

o removeEnd

o replace – replace the item at a given index by a new item

o peekEnd

• You must write each method from scratch. It means that any of your methods cannot call the other methods that are already implemented in the given LinkedListRec.java. This is to give you more practice about recursion.

• The class LinkedListRecTest must present to the user a text-based menu, which includes the operations that will call each method listed in 2 in LinkedListRec and the quit option.

• Each method listed in 1 above must be called by your LinkedListRecTest class to test whether it is implemented correctly.

4. Major Steps

a. Understand the related class I gave you in class.

i. LinkedListRec.java

b. Revise the class LinkedListRec to include a required method

c. Write the class LinkedListRecTest.

i. First use fixed values

ii. Then add the menu

d. Do Steps b, c incrementally. Add a method to LinkedListRec and then test it in LinkedListRecTest. Repeat for each method.

5. Detailed Hints

• If a method does not involve repetitive handling of the data structure, it does not make sense to use recursion.

• These methods should not be implemented using recursion:

o empty

o addAtHead

o removeFront

o peekFront

• The public wrapper methods for the corresponding private recursive methods are:

o public int size()

o public String toString()

o public void addAtEnd(E newItem)

o public E peekEnd()

o public void removeEnd()

o public void insertBefore(E target, E newItem)

o public void insertAfter(E target, E newItem)

o public void remove(int index)

o public void replace(int index, E newItem)

Each public method above must call its private recursive counterpart method in its method body. See how the original LinkedListRec class in the book (also given to you in LinkedListRec.java) does this. You need to come up with their private recursive counterpart methods.

PROVIDED CODE

Explanation / Answer

//LinkedListRec.java

package com.test;

public class LinkedListRec<E> {

/** The list head */

private Node<E> head;

/** A Node is the building block for a single-linked list. */

private static class Node<E> {

// Data Fields

/** The reference to the data. */

private E data;

/** The reference to the next node. */

private Node<E> next;

// Constructors

/**

* Creates a new node with a null next field.

* @param dataItem The data stored

*/

private Node(E dataItem) {

data = dataItem;

next = null;

}

/**

* Creates a new node that references another node.

* @param dataItem The data stored

* @param nodeRef The node referenced by new node

*/

private Node(E dataItem, Node<E> nodeRef) {

data = dataItem;

next = nodeRef;

}

} //end class Node

/**

* Finds the size of a list.

* @param head The head of the current list

* @return The Size of the Current List

*/

private int size(Node<E> head) {

if (head == null) {

return 0;

} else {

return 1 + size(head.next);

}

}

/**

* Wrapper method for finding the size of a list.

* @return The size of the list

*/

public int size() {

return size(head);

}

/**

* Returns the string representation of a list.

* @param head The head of the current list

* @return The state of the current list

*/

private String toString(Node<E> head) {

if (head == null) {

return "";

} else {

return head.data + " " + toString(head.next);

}

}

/**

* Wrapper method for returning the string representation of a list.

* @return The string representation of the list

*/

@Override

public String toString() {

return toString(head);

}

/**

* Replaces all occurrences of oldObj with newObj.

* @post Each occurrence of oldObj has been replaced by newObj.

* @param head The head of the current list

* @param oldObj The object being removed

* @param newObj The object being inserted

*/

private void replace(Node<E> head, E oldObj, E newObj) {

if (head != null) {

if (oldObj.equals(head.data)) {

head.data = newObj;

//if replace only the first occurence, then add a return statement below:

return;

}

replace(head.next, oldObj, newObj);

}

}

/*

Wrapper method for replacing oldObj with newObj.

* @post Each occurrence of oldObj has been replaced by newObj.

* @param oldObj The object being removed

* @param newObj The object being inserted

*/

public void replace(E oldObj, E newObj) {

replace(head, oldObj, newObj);

}

/**

* Adds a new node to the end of a list.

* @param head The head of the current list

* @param data The data for the new node

*/

private void addAtEnd(Node<E> head, E data) {

// If the list has just one element, add to it.

if (head.next == null) {

head.next = new Node<E>(data);

} else {

addAtEnd(head.next, data); // Add to rest of list.

}

}

/**

* Wrapper method for adding a new node to the end of a list.

* @param data The data for the new node

*/

public void addAtEnd(E data) {

if (head == null) {

head = new Node<E>(data); // List has 1 node.

} else {

addAtEnd(head, data);

}

}

//No need recursive method

public void addAtHead(E data) {

Node<E> tmp = new Node<E>(data);

tmp.next = head;

head = tmp;

}

public boolean empty()

{

return head == null;

}

public void removeFront()

{

if(head == null)

return;

else

{

head = head.next;

}

}

public E peekFront()

{

if(head != null)

return head.data;

else

return null;

}

public E peekEnd(Node<E> head)

{

if(head.next == null)

return head.data;

else

return peekEnd(head.next);

}

public E peekEnd()

{

return peekEnd(head);

}

public void removeEnd(Node<E> head)

{

if(head.next == null)

head = null;

else if(head.next.next == null)

head.next=null;

else

removeEnd(head.next);

}

public void removeEnd()

{

removeEnd(head);

}

public void insertBefore(Node<E> head, E target, E newItem)

{

if(head == null)

return;

if(head.next.data == target)

{

Node<E> n = new Node<E>(newItem);

n.next = head.next;

head.next = n;

}

else

insertBefore(head.next, target, newItem);

}

public void insertBefore(E target, E newItem)

{

insertBefore(head, target, newItem);

}

public void insertAfter(Node<E> head, E target, E newItem)

{

if(head == null)

return;

if(head.data == target)

{

Node<E> n = new Node<E>(newItem);

n.next = head.next;

head.next = n;

}

else

insertBefore(head.next, target, newItem);

}

public void insertAfter(E target, E newItem)

{

insertBefore(head, target, newItem);

}

public void remove(Node<E> head ,Node<E> pred,int index)

{

if(index ==0)

{

pred.next = head.next;

}

else

{

remove(head.next, pred.next, index--);

}

}

public void remove(int index)

{

remove(head.next,head,index);

}

/**

* Removes a node from a list.

* @post The first occurrence of outData is removed.

* @param head The head of the current list

* @param pred The predecessor of the list head

* @param outData The data to be removed

* @return true if the item is removed

* and false otherwise

*/

private boolean remove(Node<E> head, Node<E> pred, E outData) {

if (head == null) // Base case -- empty list.

{

return false;

} else if (head.data.equals(outData)) { // 2nd base case.

pred.next = head.next; // Remove head.

return true;

} else {

return remove(head.next, head, outData);

}

}

/**

* Wrapper method for removing a node (in LinkedListRec).

* @post The first occurrence of outData is removed.

* @param outData The data to be removed

* @return true if the item is removed,

* and false otherwise

*/

public boolean remove(E outData) {

if (head == null) {

return false;

} else if (head.data.equals(outData)) {

head = head.next;

return true;

} else {

return remove(head.next, head, outData);

}

}

}

//LinkedListRecTest.java

package com.test;

import java.util.Scanner;

public class LinkedListRecTest {

public static void main(String[] args) {

int option;

Scanner sc = new Scanner(System.in);

LinkedListRec<Integer> list = new LinkedListRec<Integer>();

while(true)

{

System.out.println("1: empty");

System.out.println("2.addAtHead");

System.out.println("3.removeFront");

System.out.println("4.peekFront");

System.out.println("5.size()");

System.out.println("6.toString()");

System.out.println("7.addAtEnd(E newItem)");

System.out.println("8.peekEnd()");

System.out.println("9.removeEnd()");

System.out.println("10.insertBefore(E target, E newItem)");

System.out.println("11.insertAfter(E target, E newItem)");

System.out.println("12.remove(int index)");

System.out.println("13.replace(int index, E newItem)");

System.out.println("14: Exit");

System.out.println("Please enter a choice to perform operation: ");

option = sc.nextInt();

boolean exit = false;

switch (option) {

case 1:

list.empty();

break;

case 2:

list.addAtEnd(5);

break;

case 3:

list.removeFront();

break;

case 4:

System.out.println("Peek front: "+ list.peekFront());

break;

case 5:

System.out.println("Size of list: "+ list.size());

break;

case 6:

list.toString();

break;

case 7:

list.addAtEnd(8);

break;

case 8:

System.out.println("Peek end: "+ list.peekEnd());

break;

case 9:

list.removeEnd();

break;

case 10:

list.insertBefore(5, 11);

break;

case 11:

list.insertAfter(5, 11);

break;

case 12:

list.remove(3);

break;

case 13:

list.replace(3, 33);

break;

case 14:

exit = true;

break;

default:

break;

}

if(exit)

break;

}

}

}

//output:

1: empty
2.addAtHead
3.removeFront
4.peekFront
5.size()
6.toString()
7.addAtEnd(E newItem)
8.peekEnd()
9.removeEnd()
10.insertBefore(E target, E newItem)
11.insertAfter(E target, E newItem)
12.remove(int index)
13.replace(int index, E newItem)
14: Exit
Please enter a choice to perform operation:
1
1: empty
2.addAtHead
3.removeFront
4.peekFront
5.size()
6.toString()
7.addAtEnd(E newItem)
8.peekEnd()
9.removeEnd()
10.insertBefore(E target, E newItem)
11.insertAfter(E target, E newItem)
12.remove(int index)
13.replace(int index, E newItem)
14: Exit
Please enter a choice to perform operation:
1
1: empty
2.addAtHead
3.removeFront
4.peekFront
5.size()
6.toString()
7.addAtEnd(E newItem)
8.peekEnd()
9.removeEnd()
10.insertBefore(E target, E newItem)
11.insertAfter(E target, E newItem)
12.remove(int index)
13.replace(int index, E newItem)
14: Exit
Please enter a choice to perform operation:
6
1: empty
2.addAtHead
3.removeFront
4.peekFront
5.size()
6.toString()
7.addAtEnd(E newItem)
8.peekEnd()
9.removeEnd()
10.insertBefore(E target, E newItem)
11.insertAfter(E target, E newItem)
12.remove(int index)
13.replace(int index, E newItem)
14: Exit
Please enter a choice to perform operation:
14