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.
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 this code an IntLinkedList class
public class IntLinkedList {
private Node head;
public void addFirst(int data) {
head = new Node(data, head);
}
public Node copy(){
Node current = head; // used to iterate over original list
Node newList = null; // head of the new list
Node tail = null; // point to last node in new list
while (current != null)
{
// special case for the first new node
if (newList == null)
{
newList = new Node(current.data, null);
tail = newList;
}
else
{
tail.next = new Node(current.data, null);
tail = tail.next;
}
current = current.next;
}
return newList;
}
private class Node {
int data;
Node next;
Node(int data, Node next) {
this.data = data;
this.next = next;
}
}
}
And I'm trying to test the copy method with the following JUnit code
public class IntLinkedListTest {
/** Reference to linked list under test */
private IntLinkedList lst;
/** Creates a linked list for testing. */
#Before
public void setUp() {
lst = new IntLinkedList();
lst.addFirst(30);
lst.addFirst(10);
lst.addFirst(40);
lst.addFirst(20);
}
/** Tests copying a non-empty list. */
#Test
public void testCopy() {
IntLinkedList cpy = lst.copy();
assertEquals(lst.toString(), cpy.toString());
}
}
I want to get a list returned from the IntLinkedList class from the Copy() method and tested in JUnit. I tried returned type IntLinkedList and Object too but I keep getting errors like "Type mismatch: cannot convert from IntLinkedList.Node to IntLinkedList". I have very little experience with LinkedList but I'm experienced with java classes, references to objects, but this is new territory for me. Can anyone help?
Solution:- You are comparing Node class toString with IntLinkedList class toString hence the Junit failure , Try overriding the toString() method of the Node and IntLinkedList class you will clearly see the stack trace as
org.junit.ComparisonFailure: expected:<[IntLinkedList [head=Node [data=20, next=Node [data=40, next=Node [data=10, next=Node [data=30, next=null]]]]]]> but was:<[Node [data=20, next=Node [data=40, next=Node [data=10, next=Node [data=30, next=null]]]]]>
This Junit is working as expected
#Test
public void testCopy() {
IntLinkedList.Node cpy = lst.copy();
assertEquals(lst.copy().toString(), cpy.toString());
}
Edit:-
I have made one minor change to make IntLinkedList.Node work since your Node class is private, hence I changed the signature to static to make the junit work i.e.
static class Node {
This is the final IntLinkedList copy() method with a more elegant solution to my problem. I'm only posting the copy() method since the IntLinkedList class stays the same and JUnit testing stays the same. Note: In the IntLinkedList class the only thing that changes is the copy() method
public IntLinkedList copy(){
IntLinkedList newList = new IntLinkedList();
Node current = head; // used to iterate over original list
Node tail = null; // point to last node in new list
while (current != null)
{
// special case for the first new node
if (newList.head == null)
{
newList.head = new Node(current.data, null);
tail = newList.head;
}
else
{
tail.next = new Node(current.data, null);
tail = tail.next;
}
current = current.next;
}
return newList;
}
Hm.
Your copy() should imho not return Node but IntLinkedList
So you need to adjust your code of copy() accordingly.
Also, implement equals() (and hashCode()) in your IntLinkedList class.
The equals implementation should match your expectation of when two IntLinkedList are equal.
Later in the test, use InLinkedList copy = copy(orig) and compare the result with Assert.equals(orig, copy).
I am calling a constructor in a method to insert new nodes.While I am adding new node default constructor is creating new node with default values . I want to just insert values using insert method as in below code . Is there any way I may avoid first node being default.
class Node {
Node right, left;
int data = 0;
Node() {
}
Node(int data) {
this.data = data;
}
public void insert(int value) {
if (value <= data) {
if (left == null) {
left = new Node(value);
} else {
left.insert(value);
}
} else {
if (right == null) {
right = new Node(value);
} else {
right.insert(value);
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Node new_node=new Node();//creating first node with 0 value
new_node.insert(5);
new_node.insert(4);
new_node.insert(9);
new_node.insert(23);
new_node.insert(70);
new_node.display();
}
}
You could use the first value as the first element:
Node new_node = new Node(5); // create 1st node with 1st value
Or you could define a new default constructor with a value that you don't expect to be in the list (let's say -1), but you'd have to be careful about this element in your list that is not really part of the list, and that makes implementing other operations trickier:
Node() { data = -1; }
But all this is symptom of a bigger problem: you shouldn't handle the head of your list in the Node class. It'd be better to create a new class, let's call it MyList and define a Node head attribute on it, and all insert/update/delete/search operations should be implemented on that class.
It's important to keep the head separate, because there will be operations that modify the head. For example, your insert() method doesn't consider the case when the node to insert should go at the beginning of the existing list.
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;
}