Help making a singly linked list in Java - java

This is for homework but please know that I have looked online for help (such as http://www.sethi.org/classes/class_stuff/cis435/others/notes-java/data/collections/lists/simple-linked-list.html) and my textbook but I am still having some issues.
Any help would be appreciated...
Right now I'm trying to just insert values in but nothing is working. Whether it's the first item, whether it's being added as the last one, or somewhere in between.
Node header = null; // First element of list.
Node back = null; // Last element of list.
public void insert(int i, double value){ //insert value before i-th element
Node e = new Node();
e.num = value;
Node curr = header;
for(int x=0;x<i;x++) {
if (i == 1) { //we want to insert as first thing
if (size == 0) { //its the FIRST time we add something
header.next = e;
e.next = back;
break;
} else if (size == 1){
e.next = header.next; //i.e. the second thing in the list
header.next = e;
break;
} else {
e.next = header.next.next; //i.e. the second thing in the list
header.next = e;
break;
}
}
else if (x == (i-1)) {
e.next = curr.next;
curr.next = e;
break;
}
curr = curr.next;
}
size = size+1;
}
Not really sure why it isn't working.
Thanks!

For some reason, people who are still learning to program make things far more complicated then they need to be. I did it when I was learning java, I still do it when I am just getting into a new language, and students that I have marked find new and amazing ways to do it. You have more going on in your insert then there needs to be, for example, a method that inserts a value at a specific index should not check if it's the first item to be inserted (not saying it shouldn't check bounds). Here is the pseudo code of what I would do.
insert(index, value)
if index>size
throw null pointer
traverse to index -1 //lets call this nodeI
create newnode and set value
set newnode.next to nodeI.next
set nodeI.next to newnode
increase size.
Couple of handy hints for you, you should have a function to get an element from the link list, something that returns a node? public node elementAt(int index) for example? use that to traverse the linked list. If you want to append to the Linked list, try this
append(value)
insert(size-1,value)
and if you want to insert at the beginning? same idea
insert(value)
insert(0,value)

In the line e.next = header.next.next what would happen if header.next points to a 'null'? Is it possible to get there?
What are the corner cases you have to deal with and have you taken them all into account?
Can you start with the simplest case first, adding either an element to the front or an element to the back? Then use those functions to implement the insert?

A few suggestions:
implement java.util.List
Think about generics
Read this.
Start with "insert at the end" before you think about "insert at i".

I have tried a simple program, which will be useful for you guys, I am also learning Java, please bear with me for any mistakes, but this program works fine.
I am posting a very simple singly linked list program in Java, which I tried out today.
I hope it will help all.
LinkList.java
class LinkList
{
public static void main(String args[])
{
Node node = new Node(1);
node.addAtLast(2);
node.addAtLast(3);
node.addAtLast(4);
node.addAtLast(5);
node.printList();
}
}
Node.java
class Node
{
private int data;
private Node link;
public Node(int mydata)
{
data = mydata;
link = null;
}
public void printList()
{
System.out.print("|"+data+"|"+"->");
if(link != null)
{
//recursive call
link.printList();
}
else
{
//marking end of list as NULL
System.out.print("|NULL|");
}
}
public void addAtLast(int mydata)
{
if(link == null)
{
link = new Node(mydata);
}
else
{
link.addAtLast(mydata);
}
}
}
OUTPUT :
The below is our output
|1|->|2|->|3|->|4|->|5|->|NULL|

Related

Subtraction between two nodes

i've to do write a code to solve this problem:
-Do the subtraction between two nodes p and q, where the substraction p - q is the list that contains all the elements that appear in p and not in q, knowing that p and q are ordered lists.
I tried to write a code and i know that it can't work...can you help me please to solve this problem? thank you very much!
class Node{
public int elem;
public Node next;
public Node(int elem, Node next){
this.elem = elem;
this.next = next;
}
}
public class Main{
public static Node diff(Node p, Node q){
if( p.elem == q.elem )
return diff(p.next, q.next);
else if(p.elem < q.elem){
return new Node (p.elem, diff(p.next, q.next));
else
return new Node(p.elem, diff(p.next, q.next));
}
public static void main(String[] args){
//.......
}
}
Your recursion never ends, since each return statement in your recursion method calls itself, which will lead your code to a Stack Overflow.
To solve this, you should decompose the problem.
First of all, let's find the base cases.
These are the cases where the recursion ends, and there's two for your problem:
If p == null, i.e. if the linked list contains no more items, then the work is done, there is nothing more to add to your result linked list.
if(p == null)
{
return null;
}
If q == null, then you should add all the remaining item in your linked list, i.e. the p node itself.
if(q == null)
{
return p;
}
There is 3 more possible cases, where recursion occurs:
If p.elem == q.elem then the node should not be added, and we should go to the next node for each linked list. Since the list are ordered, there is no way this node could be useful later.
if(p.elem == q.elem)
{
return diff(p.next, q.next);
}
If p.elem > q.elem the node might be useful, but we do not know yet. The next nodes of the second linked list might be equals, so we just skip to the next node for the second linked list.
if (p.elem > q.elem)
{
return diff(p, q.next);
}
There is only one case left, if p.elem < q.elem. This is it, we are sure that this node is absent from the second linked list, so we add a new node to our result.
return new Node(p.elem, diff(p.next, q);
Note that you do not need else statement in each case since there is a return in each of your cases.
Hope it helps!

Java, Doubly-Link List: Is my logic wrong?

I'm having trouble with a homework assignment, moving through a doubly linked list using an iterator. The following is the method that seems to be the problem, but it seems logically correct to me. I have a runner file that I'm using to pass a list, the runner file prints out both forwards and backwards to see if my links are working correctly. If I add a item using the add(T element) method it works fine both forwards and backwards. However, if I add an item using the add(T element, int index) method the list will output correctly forwards but on the backwards iterator the newly added item isn't in the output.
which leaves me to suspect current.getNextNode().setPriorNode(newNode); is the problem but it seems like it would be correct to me, or am I wrong?
Thanks you!
UPDATE: I edited the code with the fix for incase anyone else has the same problem in the future.
public void add(T element) {
Node<T> node = new Node(element);
if (itsFirstNode == null) {
itsFirstNode = node;
itsLastNode = node;
}
else {
itsLastNode.setNextNode(node);
node.setPriorNode(itsLastNode);
itsLastNode = node;
}
size++;
} // end of add() method
public void add(T element, int index) {
int counter = 0;
Node<T> newNode = new Node(element);
Node<T> current = itsFirstNode;
while (current.getNextNode() != null ) {
if (counter == index - 1 )
break;
current = current.getNextNode();
counter++;
}
newNode.setNextNode(current.getNextNode());
current.getNextNode().setPriorNode(newNode);
newNode.setPriorNode(current);
current.setNextNode(newNode);
size++;
} // end of Overloaded add() method
newNode.setNextNode(current.getNextNode());
current.setNextNode(newNode);
newNode has next one set correctly, current has next one as newNode
newNode.setPriorNode(current);
newNode has prior set correctly
current.getNextNode().setPriorNode(newNode);
current.getNextNode() is newNode, so you set newNode as the prior of newNode. It should work if you move this line two lines earlier
instead of
current.getNextNode().setPriorNode(newNode);
try
newNode.getNextNode().setPriorNode(newNode);
You can use following code in last 5 line
newNode.setNextNode(current.getNextNode());
current.getNextNode().setPriorNode(newNode);
current.setNextNode(newNode);
newNode.setPriorNode(current);
size++;

Add to front method of linked list if there are no duplicate items, otherwise remove the duplicate item

I am having a lot of difficulty figuring out the add method of a linked list. My assignment says to:
Implement this method, public void add(E item), inside MoveToFront
class. The method behaves like this: when the input does not exist in
the linked list, add it at the front; otherwise remove the existing
one from the list and reinsert it to the front.
What I have done so far is create a contains and delete method that will search for the existing item in the list and then delete it. Then it will add the item to the front of the list.
public int getLength() {
Node<E> curNode = first;
int count = 0;
while (curNode != null) {
curNode = curNode.next;
count++;
}
return count;
}
public boolean Contains(E item) {
if (first == null) {
return false;
}
Node<E> currentNode = first;
while (currentNode.next != null) {
containCount++;
if (currentNode.item.equals(item)) {
return true;
}
currentNode = currentNode.next;
}
return false;
}
public E Delete(int kth) {
if (kth <= getLength()) {
Node<E> currentNode = first;
for (int i = 1; i < kth; i++) {
currentNode = currentNode.next;
}
currentNode.next = currentNode.next.next;
return currentNode.item;
} else {
return null;
}
}
public void add(E item) {
if (!Contains(item)) {
Node<E> myNode = new Node<E>(item, null);
first = myNode;
} else {
Delete(containCount);
Node<E> myNode = new Node<E>(item, null);
first = myNode;
}
}
I think you aren't properly linking the nodes. Before you set the node you're inserting as the first node, set the node's next to the old first, like this:
myNode.next = first;
first = myNode;
A couple of things:
Instead of going through the list twice to first check if it contains the item, then to find and delete it, you can rewrite delete() to just go through the list and delete if a matching item is found. You can then call this method at the beginning of your add() method.
You should keep track of the size of the list with a simple instance variable that is updated whenever an item is added or removed, and then just let getLength() return this. Going through the whole list each time is way too expensive.
First of all I see a getLength() method in your code. It is a linked list, if you are trying to get the length of it for this problem then you didn't get the data structure.
Now if we get to implementation I see from the requirement you have to add new element to the front one way or another. This is how I will do that-
Create a node and link its next to the first element of current list. This will be add method.you can do this method in the end too, it will not make much difference.
Then start searching for element in the list and if you find a match delete it. Make sure you don't match with the element you just added int the front.

Recursion of Linked List

When given an array of integers, I'm trying to change each element with the product of the integers before it.
For example, int[] array = {2,2,3,4}; is now: {2, 4, 12, 48};
I added each element to a LinkedList, and I'm trying to do this recursively.
This is what I have:
Node curr = list.getFirst();
product(curr);
public static void product(Node curr)
{
if(curr == null)
{
return;
}
else
{
int data = curr.getData() * curr.getNext().getData();
Node newNode = new Node(data);
curr.setNext(newNode);
// product(curr);
}
}
The first product works: {2,4}, but when I try to put in the recursion, I get a stackoverflow. Any suggestions??
Edit: So the reason that I'm either getting a stackoverflow or null pointer exception is because I'm updating the list, and then trying to get the next integer(but since there's only two elements in the list, there isn't a getNext()). I'm not sure how to fix this.
It looks like you were getting a bit tied up in the recursion. I modified your method to accept a Node along with the product from the previous iteration. At each step of the iteration I update the value in the already-existing List, so there is no need for using the new operator.
public static void product(Node curr, int value) {
if (curr == null) {
return;
}
else {
int data = value * curr.getData(); // compute current product
curr.setData(data); // update Node
product(curr.getNext(), data); // make recursive call
}
}
There are actually two issues with the code.
The recursion never ends, i.e. it is not actually moving to a smaller "subproblem" as the recursion is calling the same node again
and again.
After creating a new node and modifying the next we also need to connect the node "after" the next node otherwise the link will be
lost. Please check the below method which addresses both the issues.
Although I didn't do an excessive testing it is working for simple dataset.
Original List:
2->4->5->6->8->null
Multiplied List:
2->8->40->240->1920->null
public void product(Node curr) {
if (curr.getNext() == null) {
return;
} else {
int data = curr.getData() * curr.getNext().getData();
Node newNode = new Node();
newNode.setData(data);
Node nodeAfterNextNode = curr.getNext().getNext();
newNode.setNext(nodeAfterNextNode);
curr.setNext(newNode);
product(newNode);
}
}
It is because you call recursive method on the current node, so it is actually never move forward in the LinkedList. You can simply update the next node's data and call the recursive method on it. See the code below:
Node curr = list.getFirst();
product(curr);
public static void product(Node curr)
{
Node next = curr.getNext();
if(next == null)
{
return;
}
else
{
int data = curr.getData() * next.getData();
next.setData(data);
product(next);
}
}

Why would this loop infinitely? (Java)

I am trying to make an add method for a linked list, but for some reason (that is not obvious to me, in fact I came here to get help finding the error) it goes into an infinite loop every time.
EDIT: I found the error, and I will keep my original code with a comment with the corrected code
public void insert(String majorName)
{
MajorNode newNode = new MajorNode(majorName, 1);
boolean inList = false;
MajorNode current = first;
if(isEmpty())
{
first = newNode;
// inList = true;
}
else
{
while(current.next != null)
{
if(current.majorName.equalsIgnoreCase(majorName))
{
current.frequency++;
inList = true;
break;
}
else
{
current = current.next;
}
}
}
if(!inList)
{
newNode.next = first;
first = newNode;
}
}
Here is my node class if it is needed:
public class MajorNode
{
public String majorName;
public int frequency;
public MajorNode next;
public MajorNode(String majorName, int frequency)
{
this.majorName = majorName;
this.frequency = frequency;
}
public String toString()
{
return majorName + " " + frequency;
}
}
On the first call to insert(), one assumes isEmpty() returns true and consequently first is set to the newNode before newNode's next field is set to the previous (null) value of first. Thus, when the list is non-empty, the loop iterates indefinitely on the last element in the list whose next field points to itself.
Out of curiosity, why are you trying to implement your own linked list functionality rather than build upon available packages (such as java.util.LinkedList<E>)?
When you create the first node you do this:
if(!inList)
{
newNode.next = first;
first = newNode;
}
This points the first nodes next at itself... hence a loop
You should be leaving the newNode.next as null for the first node, so that when you insert the second item, you reach the end of the chain..
You will have an wrong frequency if you add a node which is similar to the last node of your List. Consider this situation (adding 2 similar nodes in the empty list)
You will add a node1 in a blank list. So first & current will point to node1. (but node1.next will be null)
If you add the same node (or a node with a same majorName), you will reach to while loop (because List is not empty now). And also, you will not enter into a while loop as well. (as your current.next is still null)
and you will end up with two noes with same majorName in your list.
I would suggest to use
while(current != null)
instead of
while(current.next != null)

Categories