Reputation: 1180
I'm studying software engineering at university, and I generally have had a pretty firm grasp on the fundamental concepts of Object Oriented Programming, but lately I've found myself falling behind on some of the concepts that aren't as easy to understand.
One major issue is that I can't get my head around class constructors; something that I know will be my downfall if I don't nip this in the bud soon.
I've asked my tutor to explain it, but it must be the way they explained it that just didn't cause me to have the "ah-hah" moment I usually do.
To help you help me, see the below example, working program (demonstrating the use and manipulation of a linked list):
Main class:
package root;
public class Node<E> {
private E nodeValue;
private Node<E> next;
public static void main (String[] args) {
try {
// Example 1: Create an empty list and print it.
SinglyLinkedList<Integer> list1 = new SinglyLinkedList<Integer>();
System.out.println("Example 1: Create an empty list.");
System.out.println(list1.printList());
// ----------------------------------------------------------
// Example 2: Create a list of 1 integer (1) using InsertNodeToTail.
System.out.println("\nExample 2: Create a list of 1 integer using InsertNodeToTail.");
SinglyLinkedList<Integer> list2 = new SinglyLinkedList<Integer>();
System.out.println("Before: " + list2.printList());
list2.insertNodeToTail(1);
System.out.println("After: " + list2.printList());
// ----------------------------------------------------------
// Example 3: Create a list of 1 integer (1) using InsertNodeToHead.
System.out.println("\nExample 3: Create a list of 1 integer using InsertNodeToHead.");
SinglyLinkedList list3 = new SinglyLinkedList();
System.out.println("Before: " + list3.printList());
list3.insertNodeToHead(1);
System.out.println("After: " + list3.printList());
// ----------------------------------------------------------
// Example 4: Create a list of 5 integers (1, 3, 5, 7, and 9)
// using InsertNodeToTail. Output: 1->3->5->7->9
System.out.println("\nExample 4: Create list 1->3->5->7->9 using InsertNodeToTail.");
// Create an array of 5 integers
int[] array4 = { 1, 3, 5, 7, 9 };
// Create the head node
SinglyLinkedList<Integer> list4 = new SinglyLinkedList<Integer>();
System.out.println("Before: " + list4.printList());
// Insert nodes
for (int i = 0; i < array4.length; i++)
list4.insertNodeToTail(array4[i]);
System.out.println("After: " + list4.printList());
// ----------------------------------------------------------
// Example 5: Create a list of 5 integers (1, 3, 5, 7, and 9)
// using InsertNodeToHead. Output: 1->3->5->7->9
System.out.println("\nExample 5: Create list 1->3->5->7->9 using InsertNodeToHead.");
// Create an array of 5 integers
int[] array5 = { 1, 3, 5, 7, 9 };
// Create the head node
SinglyLinkedList<Integer> list5 = new SinglyLinkedList<Integer>();
System.out.println("Before: " + list5.printList());
// Insert nodes
for (int i = array5.length - 1; i >= 0; i--)
list5.insertNodeToHead(array5[i]);
System.out.println("After: " + list5.printList());
// ----------------------------------------------------------
// Example 6: Insert new node before a current node
System.out.println("\nExample 6: Insert node 0 before node 1.");
// Use list2, insert node 0 before node 1
System.out.println("Before: " + list2.printList());
list2.insertNodeBefore(0, 1);
System.out.println("After: " + list2.printList());
// ----------------------------------------------------------
// Example 7: Insert new node before a current node
System.out.println("\nExample 7: Insert node 4 before node 5.");
// Use list4, insert node 4 before node 5
System.out.println("Before: " + list4.printList());
list4.insertNodeBefore(4, 5);
System.out.println("After: " + list4.printList());
// ----------------------------------------------------------
// Example 8: Insert new node after a current node
System.out.println("\nExample 8: Insert node 2 after node 1.");
// Use list2, insert node 2 after node 1
System.out.println("Before: " + list2.printList());
list2.insertNodeAfter(2, 1);
System.out.println("After: " + list2.printList());
// ----------------------------------------------------------
// Example 9: Insert new node after a current node
System.out.println("\nExample 9: Insert node 10 after node 9.");
// Use list4, insert node 10 after node 9
System.out.println("Before: " + list4.printList());
list4.insertNodeAfter(10, 9);
System.out.println("After: " + list4.printList());
// ----------------------------------------------------------
// Example 10: Remove node if node value is given
System.out.println("\nExample 10: Remove node 10.");
// Use list4, remove node 10
System.out.println("Before: " + list4.printList());
list4.remove(10);
System.out.println("After: " + list4.printList());
// ----------------------------------------------------------
// Example 11: Remove node that is not in the list
System.out.println("\nExample 11: Remove node 100.");
// Use list4, remove node 100
System.out.println("Before: " + list4.printList());
list4.remove(100);
System.out.println("After: " + list4.printList());
} catch (Exception e) {
e.printStackTrace();
}
}
public Node() {
}
public Node(E nVal) {
nodeValue = nVal;
}
public Node(E nVal, Node<E> nextNode) {
nodeValue = nVal;
next = nextNode;
}
public E getNodeValue() {
return nodeValue;
}
public void setNodeValue (E nVal) {
nodeValue = nVal;
}
public Node<E> getNext() {
return next;
}
public void setNext (Node<E> n) {
next = n;
}
}
Sub-class:
package root;
import java.io.*;
public class SinglyLinkedList<E> {
private Node<E> head;
// Create an empty list
public SinglyLinkedList() {
head = null;
}
// Access to the entire linked list (read only)
public Node<E> getHead() {
return head;
}
// Insert a node with node value = nVal as the last node
public void insertNodeToTail(E nVal) {
Node<E> lastNode = new Node<E>();
lastNode.setNodeValue(nVal);
if (head == null) {
head = lastNode;
return;
}
Node<E> curr = head;
while (curr.getNext() != null) {
curr = curr.getNext();
}
curr.setNext(lastNode);
}
// Insert a node with node value = nval as the first node
public void insertNodeToHead(E nVal) {
Node<E> newHead = new Node<E>();
newHead.setNodeValue(nVal);
newHead.setNext(head);
head = newHead;
}
// Insert new node nVal to the list before current node curVal
public void insertNodeBefore(E nVal, E curVal) {
Node<E> newNode = new Node<E>(nVal);
Node<E> curr = head;
Node<E> prev = null;
if (head.getNodeValue() == curVal) {
newNode.setNext(head);
head = newNode;
return;
}
// scan until locate node or come to end of list
while (curr != null) {
// have a match
if (curr.getNodeValue() == curVal) {
// insert node
newNode.setNext(curr);
prev.setNext(newNode);
break;
} else {
// advanced curr and prev
prev = curr;
curr = curr.getNext();
}
}
}
// Insert new node nVal to the list after current node curVal
public void insertNodeAfter(E nVal, E curVal) {
Node<E> newNode = new Node<E>();
newNode.setNodeValue(nVal);
Node<E> curr = head.getNext();
Node<E> prev = head;
//scan until locate a node or come to the end of the list
while (prev != null) {
//have a match
if (prev.getNodeValue().equals(curVal)) {
//insert node
newNode.setNext(curr);
prev.setNext(newNode);
break;
} else {
//advance curr and prev
prev = curr;
curr = curr.getNext();
}
}
}
// Remove the node containing item nVal
public void remove(E nVal) throws IOException {
if (head == null) {
throw new IOException("List empty!");
} else {
Node<E> curr = head;
Node<E> prev = null;
// becomes true if we locate target
boolean foundItem = false;
// scan until locate nodeVal or come to end of list
while (curr != null && !foundItem) {
// have a match
if (curr.getNodeValue() == nVal) {
// if current node is the first node
// remove first node by moving head to next node
if (prev == null) {
head = head.getNext();
} else { // erase intermediate node
prev.setNext(curr.getNext());
}
foundItem = true;
} else {
// advanced curr and prev
prev = curr;
curr = curr.getNext();
}
}
}
}
public String printList() {
String outputList = "";
Node<E> temp = head;
if (temp == null) {
return "List empty!";
}
do {
// Print head node value
outputList += temp.getNodeValue().toString();
// Move to next node
temp = temp.getNext();
// if next node is not empty, print ->
// else print end of line then break the loop
if (temp != null) {
outputList += "->";
} else {
break;
}
} while (true);
// the loop terminates itself when it reaches to
// end of the list
return outputList;
}
}
Can anyone explain what the purpose of the constructors in the generic Node<E>
(Main) class are?
In what situation(s) should they be called upon?
Upvotes: 0
Views: 120
Reputation: 337
You have three constructors:
public Node() {
}
public Node(E nVal) {
nodeValue = nVal;
}
public Node(E nVal, Node<E> nextNode) {
nodeValue = nVal;
next = nextNode;
}
The first one is the default constructor, taking no arguments. It instantiates an Object of Class Node.
The second one takes argument (E nVal); nVal is of Type E, therefore the instantiated Node-Object will be of Type Node<nVal>.
The third constructor takes two arguments(E nVal, Node nextNode); it does the same as the second constructor plus it sets the next Node in the list, nextNode; this reference is then stored in next variable of the instantiated Object.
Upvotes: 1
Reputation: 5843
Each constructor creates a new object instance. The default constructor does not take any arguments, and if you don't supply any of your own code also does nothing to the new object.
For convenience one usually creates constructors with arguments and/or with code inside the constructor, so that the returned new object instance is pre-configured with some data.
This is especially useful if, for example, the data will never change after construction. Another use case is that any object instance you will ever get is adhering to certain rules - which you can only safely do by taking care of these rules inside the constructor, before giving the object instance away to be used.
Upvotes: 1
Reputation: 69440
You can call public Node() {
if you want to create a new Node and do not have any data.
public Node(E nVal) {
can be called if you wand to create a new node with a value.
Node(E nVal, Node<E> nextNode)
is called, if you have nodeValue
and nextNode
Upvotes: 1