I got this assignment to create an equals method for doubly linked list. So far I got the code I posted below. It passes some of the tests, but not all. The failures do have the same expected value as the actual value, but I still get some AssertionErrors.
Ive been messing and trying to change things for quite some time now, but I cant seem to figure it out on my own. Nor can I find any good examples on the internet. I've tried using Eclipse to generate the equals method, but that too does not pass all the tests.
I know you do not give away free answers here, but could someone maybe point to the mistake in the code?
/**
* This method should return true iff the values of this list
* and that are identical and in the same order.
* #param that list to compare this to.
* #return true iff the values are identical and in the same order
*/
public boolean equals(Object that) {
if (that == null)
return false;
if (!(that instanceof DoublyLinkedList) )
return false;
DoublyLinkedList<E> other = (DoublyLinkedList<E>) that;
if (header == null&&other.header != null)
return false;
if (trailer == null&&other.trailer != null)
return false;
while (header.getNext() != trailer){
if (!(header.equals(other.header))){
return false;
}
header = header.getNext();
other.header = other.header.getNext();
}
return true;
}
Edit, per request the failed tests en DLL class:
public static class DoublyLinkedList<E> {
private Node<E> header;
private Node<E> trailer;
/**
* Constructor that creates an empty DLL
*/
public DoublyLinkedList() {
this.header = new Node<>(null, null, null);
this.trailer = new Node<>(null, header, null);
this.header.setNext(trailer);
}
/**
* #return if the list is empty.
*/
public boolean isEmpty() {
return this.header.getNext() == this.trailer;
}
/**
* #return the first element of the list.
*/
public E getFirst() {
if (isEmpty()) return null;
return this.header.getNext().getElement();
}
/**
* #return the last element of the list.
*/
public E getLast() {
if (isEmpty()) return null;
return this.trailer.getPrevious().getElement();
}
/**
* Adds a new Node to the beginning of the list,
* containing the specified value.
* #param value for the new first node to hold.
*/
public void addFirst(E element) {
Node<E> newNode = new Node<>(element, header, header.getNext());
header.getNext().setPrevious(newNode);
header.setNext(newNode);
}
/**
* This method should return true iff the values of this list
* and that are identical and in the same order.
* #param that list to compare this to.
* #return true iff the values are identical and in the same order
*/
public boolean equals(Object that) {
if (that == null)
return false;
if (!(that instanceof DoublyLinkedList) )
return false;
DoublyLinkedList<E> other = (DoublyLinkedList<E>) that;
if (header == null&&other.header != null)
return false;
if (trailer == null&&other.trailer != null)
return false;
while (header.getNext() != trailer){
if (!(header.equals(other.header))){
return false;
}
header = header.getNext();
other.header = other.header.getNext();
}
return true;
}
/**
* Simple toString for testing purposes. Please note that solutions that use the
* .toString() to implement the .equals() method will be rejected.
*/
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("DoublyLinkedList<");
Node<E> finger = header.getNext();
while (finger != trailer) {
sb.append(finger.toString());
if (finger.getNext() != trailer) {
sb.append("-");
}
finger = finger.getNext();
}
sb.append(">");
return sb.toString();
}
}
And the tests:
#Test
public void testEqualsCopy() {
Solution.DoublyLinkedList<Integer> dll1 = createDLL(2);
Solution.DoublyLinkedList<Integer> dll2 = createDLL(2);
assertEquals(dll1, dll2);
}
#Test
// Both lists contain only the entry 42.
public void testTwoEqualLists() {
Solution.DoublyLinkedList<Integer> dll1 = new Solution.DoublyLinkedList<>();
Solution.DoublyLinkedList<Integer> dll2 = new Solution.DoublyLinkedList<>();
dll1.addFirst(42);
dll2.addFirst(42);
assertEquals(dll1, dll2);
}
and the errors:
testEqualsCopy(UTest) failed: 'java.lang.AssertionError: expected: Solution$DoublyLinkedList<DoublyLinkedList<1-0>> but was: Solution$DoublyLinkedList<DoublyLinkedList<1-0>>'
testTwoEqualLists(UTest) failed: 'java.lang.AssertionError: expected: Solution$DoublyLinkedList<DoublyLinkedList<42>> but was: Solution$DoublyLinkedList<DoublyLinkedList<42>>'
Since, there's quite a gap between what I think a doubly linked list should look like and what you have, I would like to add my sample implementation instead. It does away with the dummy header and trailer nodes which IMHO aren't required at all.
public class DoublyLinkedList<E> {
private Node<E> header;
private Node<E> trailer;
/**
* #return if the list is empty.
*/
public boolean isEmpty() {
return header == null;
}
/**
* #return the first element of the list.
*/
public E getFirst() {
return header != null ? header.getElement() : null;
}
/**
* #return the last element of the list.
*/
public E getLast() {
return trailer != null ? trailer.getElement() : null;
}
/**
* Adds a new Node to the beginning of the list,
* containing the specified value.
* #param value for the new first node to hold.
*/
public void addFirst(E element) {
Node<E> newNode = new Node<E>(element, null, header);
header = newNode;
if (trailer == null) {
trailer = newNode;
}
}
/**
* This method should return true if the values of this list and that are
* identical and in the same order.
*
* #param that
* list to compare this to.
* #return true if the values are identical and in the same order
*/
#SuppressWarnings("unchecked")
public boolean equals(Object that) {
if (!(that instanceof DoublyLinkedList))
return false;
DoublyLinkedList<E> other = (DoublyLinkedList<E>) that;
// if lists are empty
if (header == null) {
return other.header == null ? true : false;
}
if (!header.equals(other.header))
return false;
// Just one element
if (header == trailer) {
return true;
}
if (!trailer.equals(other.trailer))
return false;
Node<E> thisNode = header;
Node<E> otherNode = other.header;
while (thisNode.getNext() != trailer) {
thisNode = thisNode.getNext();
otherNode = otherNode.getNext();
if (!(thisNode.equals(otherNode))) {
return false;
}
}
return true;
}
/**
* Simple toString for testing purposes. Please note that solutions that use the
* .toString() to implement the .equals() method will be rejected.
*/
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("DoublyLinkedList<");
Node<E> finger = header;
while (finger != null) {
sb.append(finger.toString());
if (finger.getNext() != null) {
sb.append("-");
}
finger = finger.getNext();
}
sb.append(">");
return sb.toString();
}
}
Here's what my Node class looks like. Not many changes here.
public class Node<E> {
private E element;
private Node<E> previous;
private Node<E> next;
public Node<E> getPrevious() {
return previous;
}
public Node<E> getNext() {
return next;
}
public E getElement() {
return element;
}
public Node(E element, Node<E> previous, Node<E> next) {
this.element = element;
this.previous = previous;
this.next = next;
}
#Override
#SuppressWarnings("unchecked")
public boolean equals(Object that) {
if (!(that instanceof Node)) {
return false;
}
Node<E> other = (Node<E>) that;
if (element == null) {
return other.element == null ? true : false;
}
return element.equals(other.element);
}
#Override
public String toString() {
return element.toString();
}
}
Here's the code I used to test my implementation.
DoublyLinkedList<Integer> dll1 = new DoublyLinkedList<Integer>();
dll1.addFirst(100);
dll1.addFirst(200);
DoublyLinkedList<Integer> dll2 = new DoublyLinkedList<Integer>();
dll2.addFirst(100);
dll2.addFirst(200);
DoublyLinkedList<Integer> dll3 = new DoublyLinkedList<Integer>();
dll3.addFirst(42);
DoublyLinkedList<String> blankList1 = new DoublyLinkedList<String>();
DoublyLinkedList<String> blankList2 = new DoublyLinkedList<String>();
if (blankList1.equals(blankList2)) {
System.out.println(blankList1 + " = " + blankList2);
}
if (!dll1.equals(dll3)) {
System.out.println(dll1 + " != " + dll3);
}
if (dll1.equals(dll2)) {
System.out.println(dll1 + " = " + dll2);
}
Output :
DoublyLinkedList<> = DoublyLinkedList<>
DoublyLinkedList<200-100> != DoublyLinkedList<42>
DoublyLinkedList<200-100> = DoublyLinkedList<200-100>
Related
im working on java tree and getting stuck on setting toString for LinkedBinaryTree and mapping yes/no to left/right child.
files im using:
AbstractBinaryTree.java
import java.util.ArrayList;
import java.util.List;
/** An abstract base class providing some functionality of the BinaryTree interface. */
public abstract class AbstractBinaryTree<E> extends AbstractTree<E> implements BinaryTree<E> {
/** Returns the Position of p's sibling (or null if no sibling exists). */
public Position<E> sibling(Position<E> p) {
Position<E> parent = parent(p);
if (parent == null) { // p must be the root
return null;
}
if (p == left(parent)) { // p is a left child
return right(parent); // (right child might be null)
} else { // p is a right child
return left(parent); // (left child might be null)
}
}
/** Returns the number of children of Position p. */
public int numChildren(Position<E> p) {
int count = 0;
if (left(p) != null) {
count++;
}
if (right(p) != null) {
count++;
}
return count;
}
/** Returns an iterable collection of the Positions representing p's children. */
public Iterable<Position<E>> children(Position<E> p) {
List<Position<E>> snapshot = new ArrayList<>(2); // max capacity of 2
if (left(p) != null) {
snapshot.add(left(p));
}
if (right(p) != null) {
snapshot.add(right(p));
}
return snapshot;
}
/** Adds positions of the subtree rooted at Position p to the given snapshot. */
private void inorderSubtree(Position<E> p, List<Position<E>> snapshot) {
if (left(p) != null) {
inorderSubtree(left(p), snapshot);
}
snapshot.add(p);
if (right(p) != null) {
inorderSubtree(right(p), snapshot);
}
}
/** Returns an iterable collection of positions of the tree, reported in inorder. */
public Iterable<Position<E>> inorder() {
List<Position<E>> snapshot = new ArrayList<>();
if (!isEmpty()) {
inorderSubtree(root(), snapshot); // fill the snapshot recursively
}
return snapshot;
}
/** Overrides positions to make inorder the default order for binary trees. */
public Iterable<Position<E>> positions() {
return inorder();
}
}
AbstractTree.java
import java.util.Iterator;
import java.util.List; // for use as snapshot iterator
import java.util.ArrayList; // for use as snapshot iterator
/** An abstract base class providing some functionality of the Tree interface. */
public abstract class AbstractTree<E> implements Tree<E> {
/** Returns true if Position p has one or more children. */
public boolean isInternal(Position<E> p) {
return numChildren(p) > 0;
}
/** Returns true if Position p does not have any children. */
public boolean isExternal(Position<E> p) {
return numChildren(p) == 0;
}
/** Returns true if Position p represents the root of the tree. */
public boolean isRoot(Position<E> p) {
return p == root();
}
/** Returns the number of children of Position p. */
public int numChildren(Position<E> p) {
int count = 0;
for (Position child : children(p))
count++;
return count;
}
/** Returns the number of nodes in the tree. */
public int size() {
int count = 0;
for (Position p : positions())
count++;
return count;
}
/** Tests whether the tree is empty. */
public boolean isEmpty() {
return size() == 0;
}
/** Returns the number of levels separating Position p from the root. */
public int depth(Position<E> p) throws IllegalArgumentException {
if (isRoot(p))
return 0;
else
return 1 + depth(parent(p));
}
/** Returns the height of the tree. */
private int heightBad() { // works, but quadratic worst-case time
int h = 0;
for (Position<E> p : positions())
if (isExternal(p)) // only consider leaf positions
h = Math.max(h, depth(p));
return h;
}
/** Returns the height of the subtree rooted at Position p. */
public int height(Position<E> p) throws IllegalArgumentException {
int h = 0; // base case if p is external
for (Position<E> c : children(p))
h = Math.max(h, 1 + height(c));
return h;
}
/** This class adapts the iteration produced by positions() to return elements. */
private class ElementIterator implements Iterator<E> {
Iterator<Position<E>> posIterator = positions().iterator();
public boolean hasNext() {
return posIterator.hasNext();
}
public E next() {
return posIterator.next().getElement();
} // return element!
public void remove() {
posIterator.remove();
}
}
/** Returns an iterator of the elements stored in the tree. */
public Iterator<E> iterator() {
return new ElementIterator();
}
/** Returns an iterable collection of the positions of the tree. */
public Iterable<Position<E>> positions() {
return preorder();
}
/** Adds positions of the subtree rooted at Position p to the given snapshot using a preorder traversal. */
private void preorderSubtree(Position<E> p, List<Position<E>> snapshot) {
snapshot.add(p); // for preorder, we add position p before exploring subtrees
for (Position<E> c : children(p))
preorderSubtree(c, snapshot);
}
/** Returns an iterable collection of positions of the tree, reported in preorder. */
public Iterable<Position<E>> preorder() {
List<Position<E>> snapshot = new ArrayList<>();
if (!isEmpty())
preorderSubtree(root(), snapshot); // fill the snapshot recursively
return snapshot;
}
/** Adds positions of the subtree rooted at Position p to the given snapshot using a postorder traversal. */
private void postorderSubtree(Position<E> p, List<Position<E>> snapshot) {
for (Position<E> c : children(p))
postorderSubtree(c, snapshot);
snapshot.add(p); // for postorder, we add position p after exploring subtrees
}
/** Returns an iterable collection of positions of the tree, reported in postorder. */
public Iterable<Position<E>> postorder() {
List<Position<E>> snapshot = new ArrayList<>();
if (!isEmpty())
postorderSubtree(root(), snapshot); // fill the snapshot recursively
return snapshot;
}
/** Returns an iterable collection of positions of the tree in breadth-first order. */
public Iterable<Position<E>> breadthfirst() {
List<Position<E>> snapshot = new ArrayList<>();
if (!isEmpty()) {
Queue<Position<E>> fringe = new LinkedQueue<>();
fringe.enqueue(root()); // start with the root
while (!fringe.isEmpty()) {
Position<E> p = fringe.dequeue(); // remove from front of the queue
snapshot.add(p); // report this position
for (Position<E> c : children(p))
fringe.enqueue(c); // add children to back of queue
}
}
return snapshot;
}
}
BinaryTree.java
/** An interface for a binary tree, in which each node has at most two children. */
public interface BinaryTree<E> extends Tree<E> {
/** Returns the Position of p's left child (or null if no child exists). */
Position<E> left(Position<E> p) throws IllegalArgumentException;
/** Returns the Position of p's right child (or null if no child exists). */
Position<E> right(Position<E> p) throws IllegalArgumentException;
/** Returns the Position of p's sibling (or null if no child exists). */
Position<E> sibling(Position<E> p) throws IllegalArgumentException;
}
LinkedBinaryTree.java
/** Concrete implementation of a binary tree using a node-based, linked structure. */
public class LinkedBinaryTree<E> extends AbstractBinaryTree<E> {
// ---------------- nested Node class ----------------
protected static class Node<E> implements Position<E> {
private E element; // an element stored at this node
private Node<E> parent; // a reference to the parent node (if any)
private Node<E> left; // a reference to the left child (if any)
private Node<E> right; // a reference to the right child (if any)
/** Constructs a node with the given element and neighbors. */
public Node(E e, Node<E> above, Node<E> leftChild, Node<E> rightChild) {
element = e;
parent = above;
left = leftChild;
right = rightChild;
}
// accessor methods
public E getElement() {
return element;
}
public Node<E> getParent() {
return parent;
}
public Node<E> getLeft() {
return left;
}
public Node<E> getRight() {
return right;
}
// update methods
public void setElement(E e) {
element = e;
}
public void setParent(Node<E> parentNode) {
parent = parentNode;
}
public void setLeft(Node<E> leftChild) {
left = leftChild;
}
public void setRight(Node<E> rightChild) {
right = rightChild;
}
} // ----------- end of nested Node class -----------
/** Factory function to create a new node storing element e. */
protected Node<E> createNode(E e, Node<E> parent, Node<E> left, Node<E> right) {
return new Node<E>(e, parent, left, right);
}
// LinkedBinaryTree instance variables
protected Node<E> root = null; // root of the tree
private int size = 0; // number of nodes in the tree
// constructor
public LinkedBinaryTree() { } // constructs an empty binary tree
// nonpublic utility
/** Validates the position and returns it as a node. */
protected Node<E> validate(Position<E> p) throws IllegalArgumentException {
if (!(p instanceof Node)) {
throw new IllegalArgumentException("Not valid position type");
}
Node<E> node = (Node<E>) p; // safe cast
if (node.getParent() == node) { // our convention for defunct node
throw new IllegalArgumentException("p is no longer in the tree");
}
return node;
}
// accessor methods (not already implemented in AbstractBinaryTree)
/** Returns the number of nodes in the tree. */
public int size() {
return size;
}
/** Returns the root Position of the tree (or null if tree is empty). */
public Position<E> root() {
return root;
}
/** Returns the Position of p's parent (or null if p is root). */
public Position<E> parent(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
return node.getParent();
}
/** Returns the Position of p's left child (or null if no child exists). */
public Position<E> left(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
return node.getLeft();
}
/** Returns the Position of p's right child (or null if no child exists). */
public Position<E> right(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
return node.getRight();
}
// update methods supported by this class
/** Places element e at the root of an empty tree and returns its new Position. */
public Position<E> addRoot(E e) throws IllegalStateException {
if (!isEmpty()) {
throw new IllegalStateException("Tree is not empty");
}
root = createNode(e, null, null, null);
size = 1;
return root;
}
/** Creates a new left child of Position p storing element e; returns its Position. */
public Position<E> addLeft(Position<E> p, E e) throws IllegalArgumentException {
Node<E> parent = validate(p);
if (parent.getLeft() != null) {
throw new IllegalArgumentException("p already has a left child");
}
Node<E> child = createNode(e, parent, null, null);
parent.setLeft(child);
size++;
return child;
}
/** Creates a new right child of Position p storing element e; returns its Position. */
public Position<E> addRight(Position<E> p, E e) throws IllegalArgumentException {
Node<E> parent = validate(p);
if (parent.getRight() != null) {
throw new IllegalArgumentException("p already has a right child");
}
Node<E> child = createNode(e, parent, null, null);
parent.setRight(child);
size++;
return child;
}
/** Replaces the element at Position p with e and returns the replaced element. */
public E set(Position<E> p, E e) throws IllegalArgumentException {
Node<E> node = validate(p);
E temp = node.getElement();
node.setElement(e);
return temp;
}
/** Attaches trees t1 and t2 as left and right subtrees of external p. */
public void attach(Position<E> p, LinkedBinaryTree<E> t1, LinkedBinaryTree<E> t2) throws IllegalArgumentException {
Node<E> node = validate(p);
if (isInternal(p)) {
throw new IllegalArgumentException("p must be a leaf");
}
size += t1.size() + t2.size();
if (!t1.isEmpty()) { // attach t1 as left subtree of node
t1.root.setParent(node);
node.setLeft(t1.root);
t1.root = null;
t1.size = 0;
}
if (!t2.isEmpty()) { // attach t2 as right subtree of node
t2.root.setParent(node);
node.setRight(t2.root);
t2.root = null;
t2.size = 0;
}
}
/** Removes the node at Position p and replaces it with its child, if any. */
public E remove(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
if (numChildren(p) == 2) {
throw new IllegalArgumentException("p has two children");
}
Node<E> child = (node.getLeft() != null ? node.getLeft() : node.getRight());
if (child != null) {
child.setParent(node.getParent()); // child's grandparent becomes its parent
}
if (node == root) {
root = child; // child becomes root
} else {
Node<E> parent = node.getParent();
if (node == parent.getLeft()) {
parent.setLeft(child);
} else {
parent.setRight(child);
}
}
size--;
E temp = node.getElement();
node.setElement(null); // helps garbage collection
node.setLeft(null);
node.setRight(null);
node.setParent(node); // our convention for defunct node
return temp;
}
public String toString(Node<E> root) {
String result = "";
if (root != null) {
return "";
} else {
int depth = depth(root);
for (int i = 0; i < depth; i++) {
result = result + " ";
}
result = result + "-" + root.getElement().toString() + "\n";
result = result + toString(root.left);
result = result + toString(root.right);
}
return result;
}
} // ----------- end of LinkedBinaryTree class -----------
LinkedQueue.java
/** Realization of a FIFO queue as an adaptation of a SinglyLinkedList. All operations are performed in constant time. */
public class LinkedQueue<E> implements Queue<E> {
/** The primary storage for elements of the queue */
private SinglyLinkedList<E> list = new SinglyLinkedList<>(); // an empty list
/** Constructs an initially empty queue. */
public LinkedQueue() {
} // new queue relies on the initially empty list
/** Returns the number of elements in the queue. */
public int size() {
return list.size();
}
/** Tests whether the queue is empty. */
public boolean isEmpty() {
return list.isEmpty();
}
/** Inserts an element at the rear of the queue. */
public void enqueue(E element) {
list.addLast(element);
}
/** Returns, but does not remove, the first element of the queue. */
public E first() {
return list.first();
}
/** Removes and returns the first element of the queue. */
public E dequeue() {
return list.removeFirst();
}
/** Produces a string representation of the contents of the queue. (from front to back). This exists for debugging purposes only. */
public String toString() {
return list.toString();
}
}
Position.java
public interface Position<E> {
E getElement() throws IllegalStateException;
}
Queue.java
public interface Queue<E> {
/** Returns the number of elements in the queue. */
int size();
/** Tests whether the queue is empty. */
boolean isEmpty();
/** Inserts an element at the rear of the queue. */
void enqueue(E e);
/** Returns, but does not remove, the first element of the queue. */
E first();
/** Removes and returns the first element of the queue. */
E dequeue();
}
SinglyLinkedList.java
public class SinglyLinkedList<E> implements Cloneable {
// ---------------- nested Node class ----------------
/** Node of a singly linked list, which stores a reference to its element and to the subsequent node in the list (or null if this is the last node).
*/
private static class Node<E> {
/** The element stored at this node */
private E element; // reference to the element stored at this node
/** A reference to the subsequent node in the list */
private Node<E> next; // reference to the subsequent node in the list
/** Creates a node with the given element and next node. */
public Node(E e, Node<E> n) {
element = e;
next = n;
}
// Accessor methods
/** Returns the element stored at the node. */
public E getElement() {
return element;
}
/** Returns the node that follows this one (or null if no such node). */
public Node<E> getNext() {
return next;
}
// Modifier methods
/** Sets the node's next reference to point to Node n. */
public void setNext(Node<E> n) {
next = n;
}
} // ----------- end of nested Node class -----------
// instance variables of the SinglyLinkedList
/** The head node of the list */
private Node<E> head = null; // head node of the list (or null if empty)
/** The last node of the list */
private Node<E> tail = null; // last node of the list (or null if empty)
/** Number of nodes in the list */
private int size = 0; // number of nodes in the list
/** Constructs an initially empty list. */
public SinglyLinkedList() {
} // constructs an initially empty list
// access methods
/** Returns the number of elements in the linked list. */
public int size() {
return size;
}
/** Tests whether the linked list is empty. */
public boolean isEmpty() {
return size == 0;
}
/** Returns (but does not remove) the first element of the list. */
public E first() { // returns (but does not remove) the first element
if (isEmpty())
return null;
return head.getElement();
}
/** Returns (but does not remove) the last element of the list. */
public E last() { // returns (but does not remove) the last element
if (isEmpty())
return null;
return tail.getElement();
}
// update methods
/** Adds an element to the front of the list. */
public void addFirst(E e) { // adds element e to the front of the list
head = new Node<>(e, head); // create and link a new node
if (size == 0)
tail = head; // special case: new node becomes tail also
size++;
}
/** Adds an element to the end of the list. */
public void addLast(E e) { // adds element e to the end of the list
Node<E> newest = new Node<>(e, null); // node will eventually be the tail
if (isEmpty())
head = newest; // special case: previously empty list
else
tail.setNext(newest); // new node after existing tail
tail = newest; // new node becomes the tail
size++;
}
/** Removes and returns the first element of the list. */
public E removeFirst() { // removes and returns the first element
if (isEmpty())
return null; // nothing to remove
E answer = head.getElement();
head = head.getNext(); // will become null if list had only one node
size--;
if (size == 0)
tail = null; // special case as list is now empty
return answer;
}
public boolean equals(Object o) {
if (o == null)
return false;
if (getClass() != o.getClass())
return false;
SinglyLinkedList other = (SinglyLinkedList) o; // use nonparameterized type
if (size != other.size)
return false;
Node walkA = head; // traverse the primary list
Node walkB = other.head; // traverse the secondary list
while (walkA != null) {
if (!walkA.getElement().equals(walkB.getElement()))
return false; // mismatch
walkA = walkA.getNext();
walkB = walkB.getNext();
}
return true; // if we reach this, everything matched successfully
}
public SinglyLinkedList<E> clone() throws CloneNotSupportedException {
// always use inherited Object.clone() to create the initial copy
SinglyLinkedList<E> other = (SinglyLinkedList<E>) super.clone(); // safe cast
if (size > 0) { // we need independent chain of nodes
other.head = new Node<>(head.getElement(), null);
Node<E> walk = head.getNext(); // walk through remainder of original list
Node<E> otherTail = other.head; // remember most recently created node
while (walk != null) { // make a new node storing same element
Node<E> newest = new Node<>(walk.getElement(), null);
otherTail.setNext(newest); // link previous node to this one
otherTail = newest;
walk = walk.getNext();
}
}
return other;
}
public int hashCode() {
int h = 0;
for (Node walk = head; walk != null; walk = walk.getNext()) {
h ^= walk.getElement().hashCode(); // bitwise exclusive-or with element's code
h = (h << 5) | (h >>> 27); // 5-bit cyclic shift of composite code
}
return h;
}
/** Produces a string representation of the contents of the list. This exists for debugging purposes only. */
public String toString() {
StringBuilder sb = new StringBuilder("(");
Node<E> walk = head;
while (walk != null) {
sb.append(walk.getElement());
if (walk != tail)
sb.append(", ");
walk = walk.getNext();
}
sb.append(")");
return sb.toString();
}
}
Tree.java
import java.util.Iterator;
/** An interface for a tree where nodes can have an arbitrary number of children. */
public interface Tree<E> extends Iterable<E> {
Position<E> root();
Position<E> parent(Position<E> p) throws IllegalArgumentException;
Iterable<Position<E>> children(Position<E> p) throws IllegalArgumentException;
int numChildren(Position<E> p) throws IllegalArgumentException;
boolean isInternal(Position<E> p) throws IllegalArgumentException;
boolean isExternal(Position<E> p) throws IllegalArgumentException;
boolean isRoot(Position<E> p) throws IllegalArgumentException;
int size();
boolean isEmpty();
Iterator<E> iterator();
Iterable<Position<E>> positions();
}
and this is my driver that i have tried and struggled with!!
when i run the output for the tree is not what i am expected~~
Tree
-----
LinkedBinaryTree#5caf905d
PartA_Driver.java
import java.util.Scanner;
public class PartA_Driver {
public static void main(String[] args) {
// Output should look like
// - A |A|
// - B / \
// - C |B| |C|
// - D / \
// - E |D| |E|
// - F / \
// - G |F| |G|
LinkedBinaryTree<String> tree = new LinkedBinaryTree<>();
Position<String> A = tree.addRoot("Are you nervous?");
Position<String> B = tree.addLeft(A, "Saving Account.");
Position<String> C = tree.addRight(A, "Will you need to access most of the money within the next 5 years?");
Position<String> D = tree.addLeft(C, "Money market fund.");
Position<String> E = tree.addRight(C, "Are you willing to accept risks in exchange for higher expected returns?");
Position<String> F = tree.addLeft(E, "Stock portfolio.");
Position<String> G = tree.addRight(E, "Diversified portfolio with stocks, bonds, and short-term instruments.");
System.out.println("Tree\n-----");
System.out.println(tree.toString() + "\n");
// Are you nervous?
// Yes/ \No
// Saving Account. Will you need to access most of the
// money within the next 5 years?
// Yes/ \No
// Money market fund. Are you willing to accept risks in
// exchange for higher expected returns?
// Yes/ \No
// Stock portfolio. Diversified portfolio with stocks,
// bonds, and short-term instruments.
Scanner scanner = new Scanner(System.in);
System.out.println("Are you nervous? (yes/no)");
String decision = scanner.nextLine();
if (decision.equalsIgnoreCase("yes")) {
System.out.println("Saving Account.");
} else {
System.out.println("Will you need to access most of the money within the next 5 years? (yes/no)");
decision = scanner.nextLine();
if (decision.equalsIgnoreCase("yes")) {
System.out.println("Money market fund.");
} else {
System.out.println("Are you willing to accept risks in exchange for higher expected returns? (yes/no)");
decision = scanner.nextLine();
if (decision.equalsIgnoreCase("yes")) {
System.out.println("Stock portfolio.");
} else {
System.out.println("Diversified portfolio with stocks, bonds, and short-term instruments.");
}
}
}
}
}
I'm trying to write a method to construct a binary search tree from a given ArrayList that could contain any type of comparable object T, using:
#SuppressWarnings("unchecked")
public boolean buildFromList(ArrayList<T> list) {
if (this != null) {
root = null;
}
for (T toInsert : list) {
if (this.find(toInsert) == true) {
return false;
}
this.insert(toInsert);
}
return true;
}
but when I try to pass it an ArrayList, I get an error stating that "cannot make a static reference to a non-static type T," even though it should accept any object that implements Comparable, which should be Integer, so what am I missing? The code that I'm using to create the ArrayList to pass it is:
ArrayList<Integer> a = new ArrayList<Integer>();
a.add(1);
a.add(3);
a.add(2);
a.add(4);
a.add(-1);
System.out.println(buildFromList(a));
The full code is:
import java.util.ArrayList;
/**
* Binary Search Tree Class
*
* The head class for a binary search tree implementation.
*
* #author YOURID
* #param <Comparable> Type of data to store in the binary tree
*/
public class BinarySearchTree<T extends Comparable<T>> {
/**
* A reference pointer to the root of the tree
*/
private BinaryTreeNode<T> root;
private StringBuilder sb = new StringBuilder("");
/**
* Default constructor
*
* Creates a binary tree object with null root note (empty tree)
*/
public BinarySearchTree() {
this(null);
}
/**
* Constructor
*
* Creates a binary tree object with the given node as root
*
* #param newRoot The root of the tree
*/
public BinarySearchTree(BinaryTreeNode<T> newRoot) {
this.root = newRoot;
}
/**
* Get the root of the tree
*
* #return The root of the tree
*/
public BinaryTreeNode<T> getRoot() {
return root;
}
/**
* Set the root of the tree
*
* #param root The new root of this tree
*/
public void setRoot(BinaryTreeNode<T> root) {
this.root = root;
}
/**
* Returns the size of the tree (that is, the
* number of nodes in the tree).
*
*/
public int size() {
if (this.root != null) {
return root.size();
}
return 0;
}
/**
* Returns the height of the tree.
*
*/
public int height() {
if (root != null) {
return root.height();
}
return 0;
}
/**
* Find if an element exists
*
* Checks to see if the value val appears in the
* tree (recursively). Returns true if it appears
* and false otherwise.
*
* #param val The value to find
* #return True if the tree contains the value, false otherwise
*/
public boolean find(T val) {
return findHelper(root, val);
}
private boolean findHelper(BinaryTreeNode<T> current, T value) {
if (current == null) {
return false;
}
if (value.compareTo(current.getData()) == 0) {
return true;
}
return value.compareTo(current.getData()) < 0
? findHelper(current.getLeft(), value)
: findHelper(current.getRight(), value);
}
/**
* Insert an element
*
* Inserts val into the tree where it should appear, returning
* true on success and false otherwise
*
* #param val The value to insert
* #return True on success, false otherwise
*/
#SuppressWarnings("unchecked")
public boolean insert(T val) {
root = insertNode(root, new BinaryTreeNode<T>(val));
return this.find(val);
}
// private recursive call
#SuppressWarnings({ "rawtypes", "unchecked" })
private BinaryTreeNode insertNode(BinaryTreeNode currentParent, BinaryTreeNode newNode) {
if (currentParent == null) {
return newNode;
} else if (newNode.getData().compareTo(currentParent.getData()) > 0) {
currentParent.setRight(insertNode(currentParent.getRight(), newNode));
} else if (newNode.getData().compareTo(currentParent.getData()) < 0) {
currentParent.setLeft(insertNode(currentParent.getLeft(), newNode));
}
return currentParent;
}
/**
* Return a string that represents the data held at each
* node following the rules of an in-order traversal.
*
* Covered in class Wednesday, April 22
*/
public String inOrder() {
sb.setLength(0);
return outputInOrder(root);
}
public String outputInOrder(BinaryTreeNode<T> node) {
if (node != null) {
if (node.getLeft() != null) {
outputInOrder(node.getLeft());
}
sb.append("(" + node.getData() + ")");
if (node.getRight() != null) {
outputInOrder(node.getRight());
}
return sb.toString();
}
return "";
}
/**
* Return a string that represents the data held at each
* node following the rules of a post-order traversal.
*
* Covered in class Wednesday, April 22
*/
public String postOrder() {
sb.setLength(0);
return outputPostOrder(root);
}
public String outputPostOrder(BinaryTreeNode<T> node) {
if (node != null) {
outputPostOrder(node.getLeft());
outputPostOrder(node.getRight());
sb.append("(" + node.getData() + ")");
return sb.toString();
}
return "";
}
/**
* Build from a list
*
* Build the tree from the given list, overwriting any tree data
* previously stored in this tree. Should read from beginning to
* end of the list and repeatedly call insert() to build the tree
*
* If the tree is not empty when this method is called, you should
* empty the tree before adding any elements in list.
*
* #param list The list from which to build the tree
* #return True if successfully built, false otherwise
*/
public boolean buildFromList(ArrayList<T> list) {
if (this != null) {
root = null;
/**root.setLeft(null);
root.setRight(null);*/
}
for (T toInsert : list) {
if (this.find(toInsert) == true) {
return false;
}
this.insert(toInsert);
}
return true;
}
#SuppressWarnings("unchecked")
public boolean buildFromList(ArrayList<T> list) {
if (this != null) {
root = null;
}
for (T toInsert : list) {
if (this.find(toInsert) == true) {
return false;
}
this.insert(toInsert);
}
return true;
}
/**
* toString method
*
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
return inOrder();
}
/**
* Main method
*
* For testing, etc
*
* #param args Command line arguments
*/
public static void main(String[] args) {
BinarySearchTree<Integer> tree = new BinarySearchTree<Integer>();
BinaryTreeNode<Integer> n1 = new BinaryTreeNode<Integer>();
n1.setData(0);
BinaryTreeNode<Integer> n2 = new BinaryTreeNode<Integer>();
n2.setData(1);
BinaryTreeNode<Integer> n3 = new BinaryTreeNode<Integer>();
n3.setData(-1);
BinaryTreeNode<Integer> n4 = new BinaryTreeNode<Integer>();
n4.setData(2);
BinaryTreeNode<Integer> n5 = new BinaryTreeNode<Integer>();
n5.setData(-2);
BinaryTreeNode<Integer> n6 = new BinaryTreeNode<Integer>();
n6.setData(4);
BinaryTreeNode<Integer> n7 = new BinaryTreeNode<Integer>();
n7.setData(-6);
tree.insert(n1.getData());
tree.insert(n2.getData());
tree.insert(n3.getData());
tree.insert(n4.getData());
tree.insert(n5.getData());
tree.insert(n6.getData());
tree.insert(n7.getData());
System.out.println(tree.toString());
ArrayList<Integer> a = new ArrayList<Integer>();
a.add(1);
a.add(3);
a.add(2);
a.add(4);
a.add(-1);
System.out.println(buildFromList(a));
}
}
and I'm almost entirely certain every other part of the code compiles and runs completely fine
Have you tried to make T extend Comparable ?
Haven´t worked with Java for quite a time and don´t have an IDE here right now but I´d give it a try.
Like public boolean buildFromList(ArrayList<T extends Comparable> list) {
I'm trying to implement iterator on AVL tree, I'm stuck at this specific function:
/**
* #return an iterator for the Avl Tree. The returned iterator iterates over the tree nodes.
* in an ascending order, and does NOT implement the remove() method.
*/
public Iterator<Integer> iterator(){
List myList=new ArrayList<>();
Node counter=root;
Node counter1=root.getChildernLeft();
if(counter1==null){
myList.add(counter1);
}
Node counter1=root.getChildernLeft();
}
I added my two classes:
full code, Node class:
public class Node {
private Node parent;
private Node childernRight;
private Node childernLeft;
private int data;
private int height;
/**
* constractor
*/
public Node(int data, Node childernLeft, Node childernRight) {
this.data = data;
this.childernLeft = childernLeft;
this.childernRight = childernRight;
this.childernRight.setParent(this);
this.childernLeft.setParent(this);
}
public Node(int data) {
this.data = data;
}
public Node getParent() {
return parent;
}
public Node getChildernRight() {
return childernRight;
}
public Node getChildernLeft() {
return childernLeft;
}
public void setParent(Node parent) {
this.parent = parent;
}
public void setChildernRight(Node childernRight) {
this.childernRight = childernRight;
this.childernRight.setParent(this);
}
public void setChildernLeft(Node childernLeft) {
this.childernLeft = childernLeft;
this.childernLeft.setParent(this);
}
public int getData() {
return data;
}
public String toString() {
if (this.childernLeft != null && this.getChildernRight() != null) {
return childernLeft.toString() + "," + this.data + "," + childernRight.toString();
} else if (this.childernLeft != null && this.getChildernRight() == null) {
return childernLeft.toString() + "," + this.data;
} else if (this.childernLeft == null && this.getChildernRight() != null) {
return this.data + "," + childernRight.toString();
} else {
return this.data + "";
}
}
public int balanceFactor() {
int balanceFactor = childernRight.height - childernLeft.height;
return balanceFactor;
}
public boolean hasChildrenRight() {
if (this.childernRight != null) {
return true;
}
else{
return false;
}
}
public boolean hasChildrenLeft() {
if (this.childernLeft != null) {
return true;
}
else{
return false;
}
}
/**
* if we have many children in the tree
*/
public void addNode(Node val){
if(hasChildrenRight()&&this.data>val.data){
this.setChildernRight(val);
}
if(!hasChildrenLeft()&&this.data<val.data){
this.setChildernLeft(val);
}
if(!hasChildrenLeft()&&!hasChildrenRight()){
if(this.data>val.data){
setChildernLeft(val);
}
else{
setChildernRight(val);
}
}
if(val.data>this.data){
childernRight.addNode(val);
}
else{
childernLeft.addNode(val);
}
}
}
full code for AvlTree:`
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class AvlTree {
private Node root;
private int size;
/**
* default constructor.
*/
public AvlTree() {
this.root = null;
this.size = 0;
}
/**
* A constructor that builds a new AVL tree containing all unique values in the input
* array
*
* #param data the values to add to tree
*/
public AvlTree(int[] data) {
for (int i = 0; i < data.length; i++) {
add(data[i]);
}
}
/**
* A copy constructor that creates a deep copy of the given oop.ex4.data_structures.AvlTree. The new tree
* contains all the values of the given tree, but not necessarily in the same structure.
*
* #param avlTree an AVL tree.
*/
public AvlTree(AvlTree avlTree) {
}
/**
* Add a new node with the given key to the tree.
*
* #param newValue the value of the new node to add.
* #return true if the value to add is not already in the tree and it was successfully added,
* false otherwise.
*/
public boolean add(int newValue) {
if (root == null) {
root = new Node(newValue);
size++;
return true;
}
Node current = root;
Node parent = null;
while (current != null) {
if (current.getData() == newValue) {
return false;
}
parent = current;
if (newValue < current.getData()) {
current = current.getChildernLeft();
} else {
current = current.getChildernRight();
}
}
size++;
// when we here the new NODE Need to be chiled of Node hashmor in parent.
// addHelper is adding the new Node.2
// addHelper(newNodeToAdd, current);
return true;
}
private void addHelper(Node newNodeToAdd, Node current) {
// if (newNodeToAdd.getData() > current.getData()) {
// if (current.getChildernRight() == null) {
// current.setChildernRight(newNodeToAdd);
// } else {
// addHelper(newNodeToAdd, current.getChildernRight());
// }
// } else {
// if (current.getChildernLeft() == null) {
// current.setChildernLeft(newNodeToAdd);
// } else {
// addHelper(newNodeToAdd, current.getChildernLeft());
// }
// }
}
/**
* Check whether the tree contains the given input value.
*
* #param searchVal the value to search for.
* #return the depth of the node (0 for the root) with the given value if it was found in the tree, −1 otherwise.
*/
public int contains(int searchVal) {
Node current = root;
int depth = 0;
while (current != null) {
if (current.getData() == searchVal) {
return depth;
}
depth++;
if (searchVal < current.getData()) {
current = current.getChildernLeft();
} else {
current = current.getChildernRight();
}
}
return -1;
}
/**
* Removes the node with the given value from the tree, if it exists.
*
* #param toDelete the value to remove from the tree.
* #return true if the given value was found and deleted, false otherwise.
*/
public boolean delete(int toDelete) {
size -= 1;
return true;
}
/**
* #return the number of nodes in the tree.
*/
public int size() {
return size;
}
/**
* #return an iterator for the Avl Tree. The returned iterator iterates over the tree nodes.
* in an ascending order, and does NOT implement the remove() method.
*/
public Iterator<Integer> iterator(){
List myList=new ArrayList<>();
Node counter=root;
Node counter1=root.getChildernLeft();
if(counter1==null){
myList.add(counter1);
}
Node counter1=root.getChildernLeft();
}
/**
* Calculates the minimum number of nodes in an AVL tree of height h
*
* #param h the height of the tree (a non−negative number) in question.
* #return the minimum number of nodes in an AVL tree of the given height.
*/
public static int findMinNodes(int h) {
// I SOVLE THIS WITH ROCKISA
int counterMin = 0;
if (h == 0) {
return counterMin = 1;
}
if (h == 1) {
return counterMin = 2;
}
return (findMinNodes(h - 1) + findMinNodes(h - 2) + 1);
}
/**
* Calculates the maximum number of nodes in an AVL tree of height h.
*
* #param h the height of the tree (a non−negative number) in question.
* #return the maximum number of nodes in an AVL tree of the given height.
*/
public static int findMaxNodes(int h) {
int counterMax = 0;
for (int i = 0; i < h; i++) {
counterMax += Math.pow(h, i);
}
return counterMax;
}
/**
* #return
*/
public String toString() {
if (root == null) {
return "";
}
return root.toString();
}
//THIS IS OK
public void RotationRr(Node valRotation) {
if (valRotation == root) {
Node keepRootChild = root.getChildernRight();
root.setChildernRight(null);
}
Node parent1 = valRotation.getParent();
Node keepRightChild = valRotation.getChildernRight();///4
valRotation.setChildernRight(null);
keepRightChild.setParent(parent1);
if (!keepRightChild.hasChildrenLeft()) {
keepRightChild.setChildernLeft(valRotation);
valRotation.setParent(keepRightChild);
} else {
keepRightChild.getChildernLeft().addNode(valRotation);
}
}
public void RotationLr(Node valRotation) {
RotationLl(valRotation);
}
/**
* ........CHECK.....!!!!TODO
*
* #param valRotation
*/
public void RotationLl(Node valRotation) {
Node parent2 = valRotation.getParent();
Node keepLeftChild = valRotation.getChildernLeft();
valRotation.setChildernLeft(null);
keepLeftChild.setParent(parent2);
if (!keepLeftChild.hasChildrenRight()) {
keepLeftChild.setParent(keepLeftChild);
} else {
keepLeftChild.getChildernRight().addNode(valRotation);
}
}
public void RotationRl(Node valRotation) {
RotationRr(valRotation);
}
public static void main(String[] args) {
AvlTree avlTree = new AvlTree();
avlTree.add(7);
avlTree.add(2);
System.out.println(avlTree.contains(2));
// System.out.println(avlTree.contains(5));
avlTree = new AvlTree();
avlTree.add(2);
avlTree.add(7);
System.out.println(avlTree.contains(2));
// System.out.println(avlTree);
}
}
`
You can implement a iterator using stack
public Iterator<V> iterator() {
return new Itr();
}
private class Itr<V> implements Iterator<V> {
TreeNode<V> localNode = (TreeNode<V>) root;
Stack<TreeNode<V>> stack;
public Itr() {
stack = new ArrayStack<TreeNode<V>>();
while (localNode != null) {
stack.push(localNode);
localNode = localNode.getLeftChield();
}
}
public boolean hasNext() {
return !stack.empty();
}
public V next() {
TreeNode<V> node = stack.pop();
V v = node.getValue();
if (node.getRightChield() != null) {
node = node.getRightChield();
while (node != null) {
stack.push(node);
node = node.getLeftChield();
}
}
return v;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
I'm working on coding some data structures on my own time. I've noticed that the clone method is not copying the list as I expect. I'll post my results underneath the code as the main method is near the bottom of the class. Here is the class I have written so far:
public class DoublyLinkedList<E> implements Cloneable {
//------------nested Node class------------
private static class Node<E> {
private E element; // reference to stored element
private Node<E> prev; // reference to previous element
private Node<E> next; // reference to next element
/** The constructor that creates a node */
public Node(E e, Node<E> p, Node<E> n) {
element = e;
prev = p;
next = n;
}
// methods
/** getter for the element */
public E getElement() {
return element;
}
/** getter for previous node in list */
public Node<E> getPrev() {
return prev;
}
/** getter for next node in list */
public Node<E> getNext() {
return next;
}
/** setter for previous node */
public void setPrev(Node<E> p) {
prev = p;
}
/** setter for the next node */
public void setNext(Node<E> n) {
next = n;
}
} //------------end of nested node class------------
// instance variables of DoublyLinkedList
private Node<E> header; // head sentinel
private Node<E> trailer; // tail sentinel
private int size = 0; // number of elements in list
/** List constructor */
public DoublyLinkedList() {
header = new Node<E>(null, null, null); // create header
trailer = new Node<E>(null, header, null); // header precedes trailer
header.setNext(trailer); // trailer follows header
}
// access methods
/** Returns the size of the doubly linked list */
public int getSize() {
return size;
}
/** Tests whether the linked list is empty */
public boolean isEmpty() {
return size == 0;
}
/** Returns but does not remove the first element in the list */
public E first() {
if (isEmpty()) {
return null;
} else {
return header.getNext().getElement(); // return first node's element
}
}
/** Returns but does not remove the last element in the list */
public E last() {
if (isEmpty()) {
return null;
} else {
return trailer.getPrev().getElement(); // return last node's element
}
}
//update methods
/** Adds element e to the front of the list */
public void addFirst(E e) {
addBetween(e, header, header.getNext());
}
/** Adds element e to the back of the list */
public void addLast(E e) {
addBetween(e, trailer.getPrev(), trailer);
}
/** Removes and returns the first element of the list */
public E removeFirst() {
if (isEmpty()) {
return null;
} else {
return remove(header.getNext());
}
}
/** Removes and returns the last element of the list */
public E removeLast() {
if (isEmpty()) {
return null;
} else {
return remove(trailer.getPrev());
}
}
// private update helpers
/** Does the heavy lifting for adding an element to the list */
private void addBetween(E e, Node<E> predecessor, Node<E> successor) {
// create and link a new node
Node<E> newest = new Node<>(e, predecessor, successor);
predecessor.setNext(newest);
successor.setPrev(newest);
size++;
}
/** Does the heavy lifting for removing an element from the list */
private E remove(Node<E> node) {
Node<E> predecessor = node.getPrev();
Node<E> successor = node.getNext();
predecessor.setNext(successor);
successor.setPrev(predecessor);
size--;
return node.getElement();
}
// equals and clone methods
/** Equals method currently assumes that the list must be of the same
* type in order to be equal. This means that a doubly linked list will
* not be equal to a circularly linked list or a singly linked list even
* if the elements are identical. Because of type erasure in Java, we have
* to use Objects and casts to handle any type rather than generics. */
#SuppressWarnings({ "rawtypes" })
public boolean equals(Object o) {
if (o == null) {
return false;
}
// at this point, the classes have to be the same.
if (getClass() != o.getClass()) {
return false;
}
DoublyLinkedList other = (DoublyLinkedList) o; // use non-parameterized type (erasure)
// the size must be the same for them to be equal
if (size != other.size) {
return false;
}
Node walkA = header; // traverse primary list
Node walkB = other.header; // traverse secondary list
// We don't want to compare the trailers, so size - 1
for(int i = 0; i < size; i++) {
if (!walkA.getElement().equals(walkB.getElement())) {
return false; // mismatch
}
walkA = walkA.getNext();
walkB = walkB.getNext();
}
return true; // if we reach this, then they are equal.
}
/** The clone method that performs a deep clone of the list */
#SuppressWarnings("unchecked")
public DoublyLinkedList<E> clone() throws CloneNotSupportedException {
// always use inherited Object.clone() to create initial copy
DoublyLinkedList<E> other = (DoublyLinkedList<E>) super.clone(); // safe cast
if (size > 0) { // we need independent node chain
other.header = new Node<>(null, null, null);
other.trailer = new Node<>(null, other.header, null);
other.header.setNext(other.trailer);
Node<E> walk = header.getNext(); // walk through remainder of original list
Node<E> otherWalk = other.header;
for(int i = 0; i < size; i++) { // make new node storing same element
Node<E> newest = new Node<>(walk.getElement(), null, null);
otherWalk.setNext(newest); // link previous node to this one
otherWalk = newest;
otherWalk.setPrev(newest); // link node back to the previous one
walk = walk.getNext();
}
}
return other;
}
/** Test driver for the circularly linked list class */
#SuppressWarnings({ "rawtypes", "unchecked" })
public static void main(String args[]) {
DoublyLinkedList theList = new DoublyLinkedList();
DoublyLinkedList clonedList;
theList.addFirst(1);
theList.addFirst(2);
theList.addLast(3);
try {
clonedList = theList.clone();
System.out.println("Original List values");
while(theList.first() != null) {
System.out.println(theList.removeFirst());
}
System.out.println("Cloned List values");
while(clonedList.first() != null) {
System.out.println(clonedList.removeFirst());
}
System.out.println(theList.equals(clonedList));
} catch (CloneNotSupportedException e) {
System.err.println("I AM ERROR: List didn't clone.");
e.printStackTrace();
}
}
} //------------ end of doubly linked list class ------------
The main method in this class is just for testing. It should be pretty straightforward. However, whenever I run this code, I get the following result:
Original List values
2
1
3
Cloned List values
2
2
2
true
I'm not sure why the Cloned List values are not the same as those in the original list. I tried changing the 2 in the code to a 4 to see if I would get three 4s out of my cloned list, and indeed I did. Perhaps the list is not walking and grabs the element at the front of the list n times.
Do any of you see my mistake?
What about using the already existing API to create a correct DoubleLinkedList?
public DoublyLinkedList<E> clone() throws CloneNotSupportedException {
// always use inherited Object.clone() to create initial copy
DoublyLinkedList<E> other = new DoublyLinkedList<>();
if (size > 0) {
Node<E> walk = header.getNext();
for(int i = 0; i < size; i++) {
other.addLast(walk.getElement());
walk = walk.getNext();
}
}
return other;
}
That way you don't have to worry about your entire list logic in multiple places.
Alternatively keeping your current approach you can do the following
public DoublyLinkedList<E> clone() throws CloneNotSupportedException {
// always use inherited Object.clone() to create initial copy
DoublyLinkedList<E> other = (DoublyLinkedList<E>) super.clone();
if (size > 0) {
other.header = new Node<>(null, null, null);
other.trailer = new Node<>(null, other.header, null);
other.header.setNext(other.trailer);
Node<E> walk = header.getNext();
Node<E> otherWalk = other.header;
for(int i = 0; i < size; i++) {
Node<E> newest = new Node<>(walk.getElement(), otherWalk, otherWalk.getNext());
otherWalk.getNext().setPrev(newest);
otherWalk.setNext(newest);
otherWalk = otherWalk.getNext();
walk = walk.getNext();
}
}
return other;
}
I am learning Java SE and am currently at simple linked lists (page 687/1047 of Savitch's Absolute Java).
I am stuck at instantiating the LinkList in the main method of my demo class:
LinkedList1 list = new LinkedList1();
I tried using breakpoint and it indicates a ReflectiveOperationException.
This is the code:
public class Node1
{
private String item;
private int count;
private Node1 link;
public Node1()
{
link = null;
item = null;
count = 0;
}
public Node1(String newItem, int newCount, Node1 linkValue)
{
setData(newItem, newCount);
link = linkValue;
}
public void setData(String newItem, int newCount)
{
item = newItem;
count = newCount;
}
public void setLink(Node1 newLink)
{
link = newLink;
}
public String getItem()
{
return item;
}
public int getCount()
{
return count;
}
public Node1 getLink()
{
return link;
}
}
This is the LinkedList1 class:
public class LinkedList1
{
private Node1 head;
public LinkedList1()
{
head = null;
}
/**
* Adds a node at the start of the list with the specified data.
* The added node will be the first node in the list.
*/
public void add(String itemName, int itemCount)
{
head = new Node1(itemName, itemCount, head);
}
/**
* Removes the head node and returns true if the list contains at least
* one node. Returns false if the list is empty.
*/
public boolean deleteHeadNode()
{
if (head != null)
{
head = head.getLink();
return true;
}
else
return false;
}
/**
* Returns the number of nodes in the list.
*/
public int size()
{
int count = 0;
Node1 position = head;
while (position != null)
{
count++;
head = position.getLink();
}
return count;
}
public boolean contains(String item)
{
return (find(item) != null);
}
/**
* Finds the first node containing the target item, and returns a
* reference to that node. If the target is not in the list, null is returned.
*/
public Node1 find(String target)
{
Node1 position = head;
String itemAtPosition;
while(position != null)
{
itemAtPosition = position.getItem();
if(itemAtPosition.equals(target))
{
return position;
}
position = position.getLink();
}
return null; //target was not found
}
public void outputList()
{
Node1 position = head;
while (position != null)
{
System.out.println(position.getItem() + " " + position.getCount());
position = position.getLink();
}
}
}
I think that the problem has something to do with the constructor of Node1 having the member link of type Node1. I'm trying to understand how these data structures work and not just resort to using the built-in ArrayList(& APIs) for my projects. Can you guys have a look and point me in the right direction. Any help would be very much appreciated.
This is my main method.
public class LinkedListDemo
{
public static void main(String[] args)
{
try
{
LinkedList1 list = new LinkedList1();
list.add("apples", 1);
list.add("bananas", 2);
list.add("cantaloupe", 3);
System.out.println("List has "+ list.size() + " nodes.");
list.outputList();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
Your size method contains an infinite loop which explain why the outputs are never reached.
while (position != null)
{
count++;
head = position.getLink();
}
You are looping until position is null, but never assign anything to position and instead assign to head. Instead, you want to do
while (position != null)
{
count++;
position = position.getLink();
}
Now you would get the output
List has 3 nodes.
cantaloupe 3
bananas 2
apples 1