Linked lists method not working properly (java) - java

I've written a class which represents a polynom using a linked list (members in that list are objects of another class I made called PolyNodes).
In that class I've written this method:
public Polynom addNode (PolyNode p)
{
if (p==null) //if the polynode to be added is null, the same polynom is returned
return this;
if (_head==null) //If the head is null, the polynom is empty and the polynode becomes the polynom
{
_head=p;
return this;
}
PolyNode curr = _head, prev = null;
while(curr != null) //when curr becomes null that means we reached the end of the polynom hence we reached the end of the loop as well
{
if (p.getPower() > curr.getPower()) //Upon reaching the first term whose power is lower than p's power
{
p.setNext(curr);
if (prev == null) //When curr is the polynom's head
_head = p;
else
prev.setNext(p);
return this;
}
else if (p.getPower() == curr.getPower()) //If the polynom already has a term with the same power, p's and curr's coefficients are summed up
{
curr.setCoefficient(curr.getCoefficient() + p.getCoefficient());
return this;
}
prev = curr;
curr = curr.getNext();
}
//If the method reached outside of the loop then there is no term in the polynom whose power is smaller than p's, and p will become the last term in the polynom
p.setNext(null);
prev.setNext(p);
return this;
}
The problem started when I tried writing an addPol() method.
public Polynom addPol (Polynom other)
{
for (PolyNode temp=other._head ; temp!=null ; temp=temp.getNext())
{
addNode(temp);
}
return this;
}
I can't figure out why, but I'm getting wrong results. I went through the code dozens of times and still couldn't find anything that could cause the problem.
problem goes as follows:
when I print list1 I get:
-5.0x^20+5.0x^17+4.0x^11+6.0x^8-5.0x^7+16.0x+1.0
when I print list2 I get
-3.0x^100+2.0x^17-3.0x^4+4.0x
however, when I print list1.addPol(list2)
-3.0x^100-10.0x^20+10.0x^17+8.0x^11+12.0x^8-10.0x^7+32.0x+2.0
If anyone could please tell me what is causing this I would greatly appriciate it. thanks in advance.

When you add the node to a new list its properties get changed, so then when you move onto next you move to the next in the second list.
You would be better off just using the provided LinkedList class for this rather than trying to re-invent it yourself.

Something like:
PolyNode copy = new PolyNode();
copy.setCoefficienttemp.getCoefficient());
copy.setPower(temp.getPower());
addNode(copy);
As mentioned, otherwise temp.getNext() will be changed in the original list.
It would be more abstract to have a class Term + next == PolyNode without next.

Related

Recursively delete the last occurrence in a linked list, Java

class Link{
private int value;
private Link next;
}
I am asked to write a recursive method to delete last occurrence of a certain value, say 4.
before 2->3->4->5->4->2
after 2->3->4->5->2
The last occurrence only. I know how to delete all occurrence but I can't tell if its the last occurrence. No helper method is allowed.
The one to delete all occurrence
public Link deleteAll(){
if (next == null){
return value==4ļ¼Ÿ null:this;
}else{
if (value == 4){
return next.deleteAll();
}
next = next.deleteAll();
return this;
}
}
You can declare a pointer to the last occurred node and delete that node when reached the last element in list. Following steps explains that -
Declare two pointers one is next as in your above code another can be temp.
Iterate through list using next like you doing in deleteAll method above.
If you find the node you looking for assign that node to temp.In your case 4.
When next is null you reached the end of list now delete, whatever node is in temp delete that node. If temp is still null than no node found in given key.
EDIT:
Possible pseudo Code in case of recursion:
public void deleteLast(Node node,Node temp,Node prev, int data)
{
if(node==null)
{
if(temp!=null && temp.next.next!=null){
temp.next = temp.next.next;}
if(temp.next.next==null)
temp.next = null;
return;
}
if(node.data==data)
{
temp = prev;
}
prev = node;
deleteLast(node.next, temp, prev, int data);
}
Above code should be able to solve your problem. I made some edit in my approach which should be obvious from the code but let me describe it below
I added a prev pointer. Because if we want to delete a particular node we need to assign its next to prev node's next.So, we need the prev node not the node that we want to delete.
I think this change will follow in iterative approach too.
Not really answering your exact question, but as an alternative option, you might consider the following.
Write a recursive method to delete the first occurrence of a specified value, something like this:
public Link deleteFirst(int target) {
if (value == target) {
return next;
}
next = (next == null) ? null : next.deleteFirst(target);
return this;
}
Then you could write a reverse() method as either an iterative or recursive method as you see fit. I haven't included this, but googling should show some useful ideas.
Finally the method to remove the last occurrence of a value from the linked list could then be written like this:
public Link deleteLast(int target) {
return reverse().deleteFirst(target).reverse();
}
Note that as long as your reverse() method is linear complexity, this operation will be linear complexity as well, although constants will be higher than necessary.
The trick is to do the work on the way back -- there is no need for additional parameters, helpers or assumptions at all:
Link deleteLast(int target) {
if (next == null) {
return null;
}
Link deleted = next.deleteLast(target);
if (deleted == null) {
return value == target ? this : null;
}
if (deleted == next) {
next = deleted.next;
}
return deleted;
}

Descending ListNode Iterator Implementation

My goal in this method is to write the implementation for an iterator that iterates through elements of a listNode in descending order. (From the back to the front) I have attached my implementation of the ascending iterator. Any help in the right direction would be appreciated.
public MyDescendingDequeIterator(ListNode<E> back, ListNode<E> front) {
frontOfList = front;
nextToReturn = back;
while (nextToReturn.next != null) {
nextToReturn = nextToReturn.next;
}
}
public boolean hasNext() {
if (nextToReturn == null){
return false;
} else {
ListNode<E> current = frontOfList;
return true;
}
}
public E next() {
ListNode<E> current = frontOfList;
while ( current.next != nextToReturn ) {
current = current.next;
}
nextToReturn = current;
return nextToReturn.data;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
Provided it's a regular ListNode implementation that has only next() method, you'll need to implement the prev() method - the hasNext in that case is quite similar to the one you've implemented already.
The other approach is to hold the start of the list and to iterate each time until next element will be nextToReturn (and then update nextToReturn). This is less desired approach since you'll need to iterate O(m^2) from end to start of list of length m;
UPDATE:
OK, first of all you don't need number of elements, since it's quite opposite to the Iterator idea.
So let's say we have
public MyDescendingDequeIterator(ListNode<E> back, ListNode<E> front) {
frontOfList = front;
nextToReturn = frontOfList;
current = frontOfList;
}
Next thing is than you want to set the nextToReturn = back (now you don't use back at all). And you don't really need two variables, since nextToReturn is the current iterator.
So it transforms to:
public MyDescendingDequeIterator(ListNode<E> back, ListNode<E> front) {
frontOfList = front;
nextToReturn = back;
}
Now let's look on the next() method
As I said you don't need an indexed for here, since you've got frontOfList that has a next attribute.
So it could be:
public E next() {
ListNode<E> current = frontOfList;
while ( current.next != nextToReturn ) {
current = current.next;
}
nextToReturn = current;
return nextToReturn.data;
}
hasNext implementation should be straightforward from here. Just pay attention that according to the good coding standards the method that starts with is or has rarely changes the state of the object.
Note, that I also omit possible null checks here and other possible specific checks as is just an example of direction.
UPDATE 2:
As I think of it now, you don't need the second parameter in the constructor either, just this:
public MyDescendingDequeIterator(ListNode<E> front) {
frontOfList = front;
nextToReturn = front;
// calculate back here instead of get it as param
while ( nextToReturn.next != null) {
nextToReturn = nextToReturn.next;
}
}
UPDATE 3:
Look, it won't help to just start writing some code and expect it to work, you should sit down first and start drawing the boxes with the arrows on the piece of paper and then try to understand what each function should do.
As I said before, your hasNext() method has a bug and incorrect in general. Why do you check the null? You move from back to front, do you have a null at some place at the front? What do you need the current object for. What does it do?
The next() method should check also if you're already at the first element. Otherwise it will (and it does ) cause NullPointerException at the last element.
Try to debug first, or at least add some printouts, it helps to understand where the bug is. But first you should build the algorythm, only then start coding it, not vice versa.

Implement an algorithm to delete a node in the middle of a single linked list, given only access to that node

Example input: the node ā€˜cā€™ from the linked list a->b->c->d->e Result: nothing is returned, but the new linked list looks like a->b->d->e
I do understand that ppl have already asked this question before, but since my reputation is not high enough yet, I couldn't ask my question in that thread. so here goes my quesetion:
So in the solution, when deleting the middle node we do:
public static boolean deleteNode(LinkedListNode n) {
if (n == null || n.next == null) {
return false; // Failure
}
LinkedListNode next = n.next;
n.data = next.data;
n.next = next.next;
return true;
}
But what I don't understand is that why can't I just do n = next?
It is probably a trivial question, but I didn't seem to find a good explanation for this question
If you just do n = next then you have only changed what object your local reference variable n refers to; you haven't modified any part of the list.
The trick to "deleting" the current node is to overwrite it with the next one:
n.data = next.data;
n.next = next.next;
Now you are modifying fields of the object that is referred to by n, which is a part of the actual list.
In C++, the code you wrote would look like this:
bool deleteNode(LinkedListNode* n) {
if (n == null || (*n).next == null) {
return false; // Failure
}
LinkedListNode* next = (*n).next;
(*n).data = (*next).data;
(*n).next = (*next).next;
return true;
}
So what does that mean? When you call this method, in C++ it would look like this:
LinkedListNode* listNode = new LinkedListNode();
deleteNode(&listNode);
This is important, because that means you're just sending an address over, and not the entire object. This means that you don't actually have access to the node you gave as a parameter to the method, you only have a reference to its address.
Basically, in Java, you can't do the following C++ code:
*n = *next;
You can't modify the listNode object that's outside of the method. You only get its address. And you are only modifying the copy of its address, not the address itself.
Basically, it's because in Java, the pointer of the class is passed by value (as a copy), and primitives are also passed by value (as a copy).
somehow, it overwrites the current node which is supposed to be deleted with the
data of next node to it,and delete the next node.
LinkedListNode next = n.next;
n.data = next.data;
n.next = next.next;
That is how the code comes.

Linked list method changes other list (Java)

I've written a class which represents a polynom using a linked list (members in that list are objects of another class I made called PolyNodes). In that class I've written this method (this methods is supposed to get a paramater polynom and add it to existing polynom, returning the sum of the two polynoms while not changing the paramater):
public Polynom addPol(Polynom other)
{
if (_head==null) //If the head is null, this polynom is empty and
the other polynom becomes this polynom
{
_head=other._head;
return this;
}
if(other._head==null) //if the polynom to be added is null, the
same polynom is returned
return this;
PolyNode curr=_head, curr2=other._head, prev=null, prev2=null;
while(curr!=null && curr2!=null)
{
if(curr2.getPower()>curr.getPower())
{
System.out.println("1 " + curr2.getCoefficient());
PolyNode copy = new PolyNode(curr2.getPower() ,curr2.getCoefficient() );
System.out.println("2 " + curr2.getCoefficient());
copy.setNext(curr);
if (prev==null)
_head=copy;
else
prev.setNext(copy);
}
else if (curr2.getPower() == curr.getPower()) //If this polynom already
has a term with the same power, curr2's and curr's coefficients are summed up
{
curr.setCoefficient(curr.getCoefficient() + curr2.getCoefficient());
}
//Moving the pointer to the next node in the polynom
if(curr2.getPower()>curr.getPower())
{
prev2=curr2;
curr2=curr2.getNext();
}
else if(curr.getPower()>curr2.getPower())
{
prev=curr;
curr=curr.getNext();
}
else if(curr.getPower()==curr2.getPower())
{
prev2=curr2;
curr2=curr2.getNext();
prev=curr;
curr=curr.getNext();
}
}
if(curr2!=null) //If there are nodes left in other
{
for(;prev!=null;curr2=curr2.getNext()) //add them to this
{
PolyNode copy = new PolyNode(curr2.getPower() ,curr2.getCoefficient() );
prev.setNext(copy);
prev=curr2;
}
}
return this;
}
For some reason (that is beyond me), the paramater polynom is changed as well when I use this method, when I try to keep it unchanged. I have no clue why. can someone please help me? I'm losing hope here.
you have this line:
PolyNode curr=_head, curr2=other._head
what you're doing there is giving a reference to _head and to other._head (the references are to their memory addresses).
so when you change of the objects, all of the objects with the same memory address will be changed as well.
if you want them not to be changed you need to allocate them with a new address in the memory.
you could do that:
PolyNode curr = new PolyNode(_head)
suppose you have a copy constructor.

LinkedList remove conditions (last iterated item)

I am attempting to remove the last iterated element, with a custom iterator/linked list class. It for some reason only does this for the first item in the list (the head condition). Is there anything wrong with the conditions?
Should I, instead of the Else after If (prev=head), write If (next != null) to find middle nodes, and If (next = null) to find the last node?
Second question: to remove the items, should I also write prev.element = null (now I only have prev = null, and I suppose that erases the node but not its content.
Quite simply, what is wrong with my remove method, as I cannot figure it out myself. Thank you guys so much in advance. I have been working many hours with this but I still haven't got it working.
public E next() {
if (!hasNext())
throw new NoSuchElementException ();
prev = next;
E element = next.element;
next = next.next;
return element;
}
public void remove() {
if(prev == null) {
throw new IllegalStateException();
}
else {
if(prev == head){
head = head.next;
next = head;
}
else {
next = prev.next;
}
sizeOfList--;
prev = null;
}
}
You would need a while loop to be able to go through every node in the list until you hit the last one. As it is now, your code simply goes past the head, and then gets into the code that says sizeOfList-- and then prev = null;
You need something like this:
while (prev.next.next != null) {
prev = prev.next;
}
prev.next = null;
I do prev.next.next so that you can set the 2nd to last node in your linked list to point to a null value (which is done by prev.next = null;). Think of it this way: prev is the 2nd to last element in the list, prev.next is the last element, and obviously prev.next.next HAS to be null (because prev.next is LAST.) So once this is the case, delete the last element by setting the 2nd to last element to point to a null value.
And then decrement your list count.
This is my best guess with the given code
if(prev == head){ should change to if(prev.equals(head)){ Use equals method.
And I think you have to override equals method in the corresponding element class might definitely help.
== only checks for whether both variables refer to same object in memory, where as equals check Object state.
I hope it helps :).

Categories

Resources