So a method for part of a project requires that I check to see that an E element is already in the node list. If not, then I add the element to the list and return true (as the method is type boolean). However, I keep getting an error in my JUnit test class. So I wanted to know what is wrong with my code currently. Here is the method:
public boolean add(E element)
{
for(Node ref = first; ref != null; ref = ref.next)
{
first = new Node(element);
if(!(element.equals(ref.data)))
{
n++;
add(element);
return true;
}
else if(element.equals(ref.data))
{
return false;
}
}
return false;
}
I'm pretty sure that the way I formatted the code is wrong. I'm not really familiar with nodes as I am with arrays so that is the reason why the code may be a disgrace. And btw, n is for size.
Your method appears to be combining both a recursive approach and an iterative approach to search, and in neither case do you handle the actual adding of the new element to the list.
You didn't specify where the new element should be added (front or back), so I'll assume front. I'm also assuming that first in your code is a field of your class, because it isn't otherwise declared.
A recursive solution doesn't make much sense here and doesn't have any advantages that I can see in this case. So here's one iterative solution, which puts the new element in front if not found:
public boolean add(E element)
{
for (Node ref = first; ref != null; ref = ref.next)
{
if (element.equals(ref.data)) {
return false;
}
}
Node newFirst = new Node(element);
newFirst.next = first;
first = newFirst;
return true;
}
The logic should have two parts:
First check in the complete list if the element exists or not? If it does return false and dont do anything else go to step 2.
If element does not exist then insert it and return true.
This is shown in the following code:
public boolean add(E element)
{
boolean doesElementExist = false;
//Step 1
for(Node ref = first; ref != null; ref = ref.next)
{
if(element.equals(ref.data))
{
doesElementExist = false;
break;
}
}
//Step 2
if(!doesElementExist) {
// Now we need to add element.
Node newNode = new Node(element);
newNode.next = first;
first = newNode;
doesElementExist = true;
}
return doesElementExist;
}
Related
I need to create linked list of rectangles. Im given the class files of rectangleandpointclasses, and need to writeRectNodeandRectList`.
This is RectNode:
public class RectNode
{
private RectangleA _rect;
private RectNode _next;
public RectNode(RectangleA r)
{
_rect = r;
_next = null;
}
public RectNode(RectangleA r,RectNode n)
{
_rect = r;
_next = n;
}
public RectNode(RectNode other)
{
_rect = other._rect;
_next =other._next;
}
public RectangleA getRect()
{
return _rect;
}
public RectNode getNext()
{
return _next;
}
public void setRect(RectangleA r)
{
_rect = r;
}
public void setNext (RectNode next)
{
_next = next;
}
}
And this is part of RecList which I have a problem with:
public class RectList
{
private RectNode _head;
public RectList()
{
_head = null;
}
public void addRect(RectangleA t)
{
RectNode value = new RectNode(t,null);
RectNode next = new RectNode(t,_head);
while(next.getNext() != null)
{
next = next.getNext();
}
}
I want the order to be first-in first-out, but managed only first-in last-out by this:
public void addRect(RectangleA t)
{
RectNode next = new RectNode(t,_head);
_head = next;
}
So how I do that the way I need? I tried running trough the list by next.getNext() until the
next is null, but can`t figure out by code and implement it.
These are the issues in addRect:
There is no assignment of value to anything that relates to the list, so the node is not added.
There is no provision to update _head when it was null
If it was intended to create a dummy node that sits in from of _head (which can be a valid approach), then this idea is destroyed by walking away from that node in the loop: you have for ever lost the reference to that dummy node, yet you would need it to update _head (in case it was null)
There are several ways to do this, and I understand from your code that you want to introduce a dummy node, that sits in front of the current _head. But then you would need another reference to stay there, one that is not modified by the loop.
I would also use different variable names. value gives the impression that it is about a node's value, but this is not the case: it is a node -- the one to be added -- so I'd just call it newNode if you really need the variable at all. The name next suggests that it refers to something that precedes it, but that seems irrelevant here. As its purpose is to identify the tail of the list, why not call it tail?
1. Solution using a dummy node
public void addRect(RectangleA t)
{
final RectNode preHead = new RectNode(t, _head); // This reference will stay here
RectNode tail = preHead; // This reference will traverse the list
while (tail.getNext() != null)
{
tail = tail.getNext();
}
// Now create and append the new node immediately after the tail node:
tail.setNext(new RectNode(t, null));
// Set the new head (in case it was null, this is relevant)
_head = preHead.getNext();
}
2. Solution without dummy node
Although the solution with the dummy node does not have to distinguish between the case of an empty and non-empty list, you can avoid the use of the dummy node when you do deal separately with these cases:
public void addRect(RectangleA t)
{
if (_head == null) { // Special case, the only one where _head must change
_head = new RectNode(t, null);
} else { // The list is not empty, and _head will not change
RectNode tail = _head;
while (tail.getNext() != null)
{
tail = tail.getNext();
}
// Now create and append the new node immediately after the tail node:
tail.setNext(new RectNode(t, null));
}
}
I am working on a code that puts new elements on MyStack if they are unique. I had to copy and paste the node starting code, so I'm having a bit of trouble with an issue. I keep getting two error messages, even after trying various workarounds and I'm not really understanding why. I've even tried using some helper functions I've previously made that have worked before so I'm extra confused.
The two errors I consistently get are:
-cannot infer type arguments for MyStack.Node (actual and formal arguments differ in length)
-constructor node cannot be applied to given types. Required, no arguments, found: anything,
Here's my code:
public class MyStack<Anything>
{
private Node first, last;
private class Node<Anything>
{
Anything item;
Node next;
}
public boolean contains(Anything value)
{
for (Node curr = first; curr != null; curr = curr.next)
{
if (value.equals(curr.item)) {
return true;
}
}
return false;
}
public void add(Anything value)
//method that adds a new value to the end of the list
//COMPLETE
{
Node temp = first;
while(temp.next!=null){ //finds the end
temp=temp.next;
}
temp.next=new Node(value, null); //assigns new value
}
public void enqueue(Anything info){
if (this.contains(info)==true) { //if the info is already present
System.out.println("the stack already contains this value");
return;
}
//if we actually need to add the info
if (first == null) { //if there is nothing in the stack
Node temp= first;
first = new Node<>(info,temp);
first = temp;
return;
}
if (first != null) { //if there is already stuff
Node temp = first;
while (temp.next == null)
{ Node newNode= new Node<>(info, temp);
temp.next = newNode;
}
return;
}
}
}
As #Andreas already pointed out, Node needs a constructor.
There are a few other flaws in your Code:
Use Generics
With your Code, you can only store Objects of the class Anything, what strongly limits its reusability. Use a generic instead and you can reuse this class for many more purposes.
Linked List
I suggest, you use the paradigm of a double-linked-list. That way you do not need to find the last Node to add something to the Stack. Node now has a pointer to its previous and next element.
Use the last Object
You have the object last but never use it. To find out, whether the current object is the last one you compare the value to null. This has the effect, that storing a null value will break your List. Instead compare to the Object last, this object is unique and guarantees you, that you are at the end of the list. Both first and last are Nodes that do not contain a value and are simply used to mark the start/end of your List.
Adding elements
Using the changes above, the code in the Method enqueue(T value) becomes significantly simpler: You just check whether contains(value) and decide whether you add the value to the List or not.
All these changes applied result in following code:
public class MyStack<T extends Object> {
private Node first, last;
public MyStack() {
first = new Node(null, null, null);
last = new Node(null, null, first);
first.next = last;
}
private class Node {
T item;
Node next;
Node previous;
public Node(T item, Node next, Node previous) {
this.item = item;
this.next = next;
this.previous = previous;
}
}
public boolean contains(T value) {
for (Node curr = first.next; curr != last; curr = curr.next) {
if (value.equals(curr.item)) {
return true;
}
}
return false;
}
/**
* method that adds a new value to the end of the list
*/
public void add(T value)
{
Node secondLast = last.previous;
Node added = new Node(value, last, secondLast);
secondLast.next = added;
last.previous = added;
}
/**
* only adds value if it is not already contained by the Stack
*/
public void enqueue(T value) {
if (this.contains(value) == true) { // if the info is already present
System.out.println("the stack already contains this value");
}
else {
add(value);
}
}
public static void main(String[] args) {
MyStack<String> test = new MyStack<>();
test.add("foo");
test.add("bar");
test.add("baz");
System.out.println(test.contains("bar"));
System.out.println(test.contains("new"));
test.enqueue("baz");
test.enqueue("MyStack");
}
}
Naming
As you may have noticed, in my explanation I called this class a List. This is because it fulfills more of the characteristics of a List. A Stack usually only provides the methods push to put something at the top of the Stack and pop to remove and return the topmost Object. Optionally peek can return the topmost Object, without removing it from the Stack.
Also consider renaming the method enqueue: enqueue is used in Queues (obviously) and Queues do not forbid to add two equal Objects. So the name is misleading. I would call this method something like addIfNotContaining.
In my Opinion you should name this class to be a List and add a method get(int i) to get a specific element at a position. Naturally adding some other methods like size ect. to comply with a standard List. But I assume you already had, but did not post them because they are not related to your problem.
Multithreading
This Class is far from threadsave. But I let you figure out yourself how to make it threadsave if needed.
I have a linked list I'm given and I need to find the first value in the list via a getFirst method.I need to display an error message and quit the program if the value is null. The linked list is already given to me link so:
class MyLinkedList
{
private class Node // inner class
{
private Node link;
private int x;
}
//----------------------------------
private Node first = null; // initial value is null
//----------------------------------
public void addFirst(int d)
{
Node newNode = new Node(); // create new node
newNode.x = d; // init data field in new node
newNode.link = first; // new node points to first node
first = newNode; // first now points to new node
}
//----------------------------------
public void traverse()
{
Node p = first;
while (p != null) // do loop until p goes null
{
System.out.println(p.x); // display data
p = p.link; // move p to next node
}
}
}
//==============================================
class TestMyLinkedList
{
public static void main(String[] args)
{
MyLinkedList list = new MyLinkedList();
list.addFirst(1);
list.addFirst(2);
list.addFirst(3);
System.out.println("Numbers on list");
list.traverse();
}
}
Here's what I tried out for the method:
public static Node getFirst(Node list)
{
if (list == null)
{
System.out.println("Error!");
System.exit(1);
}
return MyLinkedList.first;
}
I know this isn't exactly right, we just started this in my class so I'm having trouble understanding what's going on with it. Thank you!
I think you should look at https://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html and get an idea for the behavior of a linked list initially. Once you have an idea on how it behaves, you can think about how to add functionality around it. Right now you just have a single method which you call more than you should. What also might help is to create an interface and document it so you know what each method should do.
You should check that first isn't null in order to do what you describe in the question. Also, it is kind of weird that the first node autoreferences itself because usually it is left in null until you add another node
notice that the first value is linked to the first Node with is null. Then you have to check two things
Node == null (you got this)
Node.next == null (you have to do this)
When Node.next == null. It means that Node is first value because it is linked to the initial Node with is null.
Then you have
public static Node getFirst(Node list)
{
// if the list is empty
if (list == null)
{
System.out.println("Error!");
System.exit(1);
} else if(list.link == null) {
// this is the first value!
return list;
} else {
// keep searching recursive with the next Node
return getFirst(list.link);
}
}
The class MyLinkedList in your question follows the pattern of a stack data structure(At the time when i am writing this answer). That is: ever time you add a new element, the new element replaces the previously added element as the first element.
I guess you want to get 1 as your first element, if you have added elements 1,2,3 in that order. Correct me if i am wrong.
In that case your linked list and it's retrieval should be like this:
(Note: i have avoided private vars , public getter , settter , etc; to make code easily readable. But readers should add them.)
class Node{ int x; Node next; }
class LinkedList
{ Node head,tail;
void add(int y)
{ Node node = new Node();
node.x=y;
if(head==null)
head = tail = node;
else
tail = tail.next = node;
}
int getFirst()
{ if(head!=null)
return head.x;
else
throw new java.util.NoSuchElementException("List is empty");
}
}
If you look at java.util.LinkedList, you will find methods that are conventionally used in linked lists. If this is not a homework question, then i suggest you do not reinvent the wheel. Just use the existing libraries.
If you have to use the stack data structure, and you cannot change it, then i suggest you have to change your getFirst() like this:
int getFirst()
{ if(tail!=null)
return tail.x;
else
throw new java.util.NoSuchElementException("List is empty");
}
If you not allowed to add Node tail in your code, then your getFirst() will look like this:
int getFirst()
{ if(head==null)
throw new java.util.NoSuchElementException("List is empty");
Node node = head;
while(node.next!=null)
node=node.next;
return node.x;
}
Here is the problem I can not resolve. I have an .xml file, not with parent and child but with grand-child and multi-grand child. Every element name is unique, so I need a method to find and return searchable element. My code so far:
public static Element findElement(Element current, String nameOfElement) {
Element searchedElement = null; // this element I want to return
List children = current.getChildren(); // current is a root element passed to method
Iterator iterator = children.iterator();
//label:
while (iterator.hasNext()) {
Element child = (Element)iterator.next();
if (child.getName().equals(nameOfElement)) {
searchedElement = child; // on some level it founds it
System.out.println("!!!"); // it's just a marker to see that action happens
//break label;
break;
}
findElement(child, nameOfElement);
}
return searchedElement;
}
Normally, when if condition is performed cycle should stop according to break, but this does not happen. Also I had an idea about adding label. (It' is commented in the code) but it also does not work. Recursion starts and erase variable searchedElement value.
I have found a solution, but it looks ugly and I wonder while upper added code doesn't work. My solution is to add instead of recursive call of findElement(child, nameOfElement); this code:
Element el = findElement(child, nameOfElement);
if (el != null && el.getName().toLowerCase().equals((nameOfElement).toLowerCase())) {
searchedElement = el;
return searchedElement;
}
Please help to find solution!
Try,
public static Element findElement(Element current, String nameOfElement) {
Element searchedElement = null; // this element I want to return
List children = current.getChildren(); // current is a root element passed to method
Iterator iterator = children.iterator();
//label:
while (iterator.hasNext()) {
Element child = (Element)iterator.next();
if (child.getName().equals(nameOfElement)) {
searchedElement = child; // on some level it founds it
System.out.println("!!!"); // it's just a marker to see that action happens
//break label;
break;
}
searchElement = findElement(child, nameOfElement);
if(searchElement != null)
return searchElement;
}
return searchedElement;
}
You just need to return the value of recursive call
public static Element findElement(Element current, String nameOfElement) {
Element searchedElement = null; // this element I want to return
List children = current.getChildren(); // current is a root element passed to method
Iterator iterator = children.iterator();
//label:
while (iterator.hasNext()) {
Element child = (Element)iterator.next();
if (child.getName().equals(nameOfElement)) {
searchedElement = child; // on some level it founds it
System.out.println("!!!"); // it's just a marker to see that action happens
//break label;
break;
}
searchedElement = findElement(child, nameOfElement);//HERE !!!
}
return searchedElement;
}
my question is in my main method, how to add multiple nodes to the linked list....What I have now with first, node2, node3..I thought was adding those nodes but I realized I don't think I'm actually doing anything with those nodes and their values, right? How do I use setData() and setNext() to add all of those nodes. Does that make sense?
ListNode<String> node4 = new ListNode<String>("Fourth", null);
ListNode<String> node3 = new ListNode<String>("Third", node4);
ListNode<String> node2 = new ListNode<String>("Second", node3);
ListNode<String> first = new ListNode<String>("First", node2);
If the above sets up the values how do I add them all?
Do I then need to set the data and next for each one of these? (This seems redundant since I seem to be setting up the value of each nodes data and next in the constructor above?)
first.setData("first");
first.setNext(node2);
node2.setData("Second");
node2.setNext(node2);
//.....
I'm trying to add all of the above nodes so I can test my addLast() method by adding a new node. However, when I call my addLast() method in main as you can see below the only thing that's printed is that addLast() value I added (and first if I call addFirst()).
Test Class
public class LinkedListDriver
{
public static void main(String[] args) {
//List<String> list = new LinkedList<String>(); //comment out this line to test your code
SinglyLinkedList<String> list = new SinglyLinkedList<String>(); //remove comment to test your code
ListNode<String> node4 = new ListNode<String>("Fourth", null);
ListNode<String> node3 = new ListNode<String>("Third", node4);
ListNode<String> node2 = new ListNode<String>("Second", node3);
ListNode<String> first = new ListNode<String>("First", node2);
ListNode value = new ListNode("First", new ListNode("Second", new ListNode("Third", null)));
//I've been messing around with this but
list.addFirst(first.getData());
list.addFirst("Second");
list.addLast("Fifth");
list.printList();
}
}
I didn't add my other two classes because I didn't think it was relevant but if you'd like to see it let me know. I'm very new this is only my second class and it's online and is poorly constructed class, please be nice lol
SinglyLinkedList class
//This class implements a very simple singly-linked list of Objects
public class SinglyLinkedList<E>
{
ListNode<E> first; // first element
public SinglyLinkedList() {
first = null;
}
public E getFirst() {
if (first == null) {
throw new NoSuchElementException();
} else
return first.getData();
}
public void addFirst(E value) {
first = new ListNode<E>(value, first);
}
// Methods below implemented by you. Note: while writing methods, keep in mind
// that you might be able to call other methods in this class to help you - you
// don't always need to start from scratch(but you'll have to recognize when)
public void addLast(E value) {
ListNode<E> temp = first;
//If list is empty make new node the first node.
if (temp == null) {
first = new ListNode <E>(value, null);
first.setNext(null);
}//Otherwise loop to end of list and add new node.
else {
while (temp.getNext() != null) {
temp = temp.getNext();
}
temp.setNext(new ListNode<E>(value, null));
}
}//end addLast
// throws an exception - you decide when and which one
public E getLast() {
ListNode<E> temp = first;
if (temp == null) {
throw new NullPointerException("There are no elements in this list to get.");
} else {
while (temp.getNext() != null) {
temp = temp.getNext();
}
return temp.getData();
}
}
// throws an exception - you decide when and which one
public E removeFirst() {
if (first == null) {
throw new NullPointerException("There are no elements in this list to remove.");
}
ListNode<E> tempRemove = first;
return null; //just so it'll compile
}
// throws an exception - you decide when and which one
public E removeLast() {
return null; //just so it'll compile
}
// return the number of elements in the list
public int size() {
return 0; //just so it'll compile
}
// return true if o is in this list, otherwise false
public boolean contains(E obj) {
return true; //just so it'll compile
}
public void printList(java.io.PrintStream out) {
if (first == null) {
System.out.println("The list is empty");
}
ListNode<E> current = first;
while (current != null) {
System.out.println(current.toString());
current = current.getNext();
}
}
public String toString() {
String s = "[";
ListNode<E> current = first;
//write code to traverse the list, adding each object on its own line
while (current.getNext() != null) {
current = current.getNext();
}
s += "]";
return s;
}
// OPTIONAL: just for fun...and a challenge
public void reverse() {
}
}
ListNode class is your basic getNext setNext, getData setData....
A couple of points, mostly summarizing the comments:
You shouldn't work with ListNode objects in main() at all - that should be the job of the SinglyLinkedList class. ListNode doesn't even need to be visible to the rest of the code, it could be a nested class in SinglyLinkedList. You should only be exchanging the data objects (Strings in this case) with SinglyLinkedList.
If you want to test for example the addLast() method, you could start with an empty list and repeatedly call list.addLast(), as Shane mentions in his answer. That way you will make sure it works when the list is empty as well as nonempty.
SinglyLinkedList<String> list = new SinglyLinkedList<String>();
list.addLast("first");
list.addLast("second");
list.addLast("third");
list.printList(System.out);
As for adding multiple nodes in a single call - this linked list doesn't have a method for that. You could add a method for adding all elements of an array for example, but you can just call addLast() sequentially with the same effect. You can create some helper method in the main class to populate the list in this way, if you want to start with some base data for testing other methods.
As a side note: if printList() takes java.io.PrintStream out as argument, you should use it instead of System.out. That is
out.println(...)
instead of
System.out.println(...)
Also, it's better to throw NoSuchElementException rather than NullPointerException as an indication that the requested element doesn't exist.
If you want a convenient way to populate the list, you could have something like this in your main class:
static <E> void addToList(SinglyLinkedList<E> list, E... values) {
for (E value : values) {
list.addLast(value);
}
}
and use it like this:
SinglyLinkedList<String> list = new SinglyLinkedList<String>();
addToList(list, "first", "second", "third");
What are you trying to do? If you're attempting to populate the linked list, all you need to do is continually call list.addLast, which will take a single parameter (the data in the new node you're adding), and deal with creating the new node and placing it in the back of the list.
You shouldn't need to create any nodes in your main, I'm assuming, as they are generally handled entirely by the linkedlist class.