Remove all linked list in Java - java

I'm learning Java & Data structures.
I made a method that removes all the linked list. Here is the code:
public class LinkedList {
...
public void purge() {
SLLNode nextNode, iterator = headNode;
while(iterator != null) {
nextNode = iterator.getNext();
iterator = null;
iterator = nextNode;
}
}
...
}
And here is the main method:
public class SinglyLinkedList {
public static void main(String[] args) {
SinglyLinkedList test = new SinglyLinkedList();
test.insert(1, 0); // insert(data, position)
test.insert(2, 1);
test.insert(3, 2);
test.insert(4, 1);
test.purge();
test.printList(); // Still prints elements!
}
}
So after all of insertion, the list is: 1-> 4 -> 2 -> 3, but the method purge() doesn't remove elements - the method printList() still prints the values in the linked list. But I can purge the linked list like:
public void new_purge() {
headNode = null;
}
But the purge() method doesn't look like have a problem.. probably it's lack of Java understanding, but why the method purge() doesn't work here?

The problem is that you are assigning headNode to a local variable SLLNode nextNode, iterator = headNode; and then set it to null but your global (class instance) variable headNode is not affected.
As a side node, In Java, you should not worry about manual memory management in such cases as the Garbage Collector will free the memory. Assuming that the nodes are internally handled by the linked list class, setting the head to null is enough.

Small mistakes in your purge method.
public void purge() {
SLLNode nextNode, iterator = headNode;
while(iterator != null) {
nextNode = iterator.getNext();
// iterator = null; -- does nothing.
iterator.setNext(null); // You want to remove the pointer on the next element
iterator = nextNode;
}
headNode = null; // Remember to clear also your head pointer.
}
But you should use LinkedList in the JAVA api.

Basically, the problem is that you are overwriting your iterator pointer rather than the node's pointer. You are not actually affecting your nodes at all.
Your new_purge method should actually work and in fact is much faster (~n rather than ~2n).

Firstly, the method purge() could be more efficient regarding memory. It'd be:
public class LinkedList {
...
public void purge() {
SLLNode iterator = headNode;
while(iterator != null) {
iterator = null;
iterator = iterator.getNext();
}
}
...
}
You can remove the variable nextNode. And can you post your method insert?

Related

Update value of a reference in recursive method - best practices

I am trying to see how I can update a reference variable in Java methods in a better way. I know that Java references are pass by value - in other words, if I change the value of the reference in a method, it wont retain it in the caller method. But at the same time, I am trying to see how I can deal with these situations better. In most cases we need to return value from a method in recursion, say its base case, just like below where I resort to maintaining a static variable to hold the new head of a linked list that is being reversed. What are the more sensible options that I can use here?.
public static LinkedList _head = null;
public static LinkedList reverseLinkedList(LinkedList head)
{
reverseLinkedListInternal( head );
return _head;
}
public static LinkedList reverseLinkedListInternal( LinkedList node )
{
if( node.next == null )
{
_head = node;
return node;
}
LinkedList tmp = reverseLinkedListInternal( node.next );
tmp.next = node;
node.next = null;
return node;
}
You just don't need the static variable here. You should be just using the return value, whereas at the moment it's simply being ignored.
This is the kind of solution I would write. Obviously this might not fall into the constraints of your exercise as it is written as if it were a method of a LinkedList, which would make a lot more sense in the real world. However the concept is the same, so hopefully it will help you to spot your mistakes.
public void reverse() {
reverseInternal(head);
}
public Node reverseInternal(Node node) {
if (node.next == null) {
return node;
}
Node reversedTail = reverseInternal(node.next);
reversedTail.next = node;
node.next = null;
return reversedTail;
}

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);
}
}

java List type variable

I have been breaking my head with below code which I made. The problem is that when I do
tail.child = null;
it is also making my childPoint's child as null.
tail is instance variable with below definition:
public List tail;
public void removeMultiLinkList() {
List headPoint = head;
while (headPoint.next != null) {
List childPoint = headPoint;
while (childPoint.child != null) {
tail.next = childPoint.child;
tail = tail.next;
tail.child=null;
childPoint = childPoint.child;
}
headPoint = headPoint.next;
}
}
I have made this method to solve the problem of multilevel link list and convert it into linear singly link by in non recurssive manner
Examine what you are doing:
tail.next = childPoint.child;
tail = tail.next;
In here, tail is childPoint.child (reference identity)
Then, you do:
tail.child=null;
This means, you actually set childPoint.child.child = null; - because chilePoint.child and tail are different names for the same object.
And then, you assign:
childPoint = childPoint.child;
But you assign childPoint to the same object you just changed - so the new childPoint's child, is null!
A very easy workaround is to copy by value (by creating a copy constructor) the elements from one list to the other.
An alternative might be to keep copying references - but without changing child at all. At the end of your algorithm, do some post-processing and set e.child = null for each element e in your list.

LinkedLists in Java; making the last node on the list point to the first node rather than contain null

I'm trying to figure out how to write a method that would modify the last node in a linkedlist and change it from null to the first node when passed the first pointer from the linked list.
I tried this which turned into a error:
public void blah()
{
Node p = first;
while (p != null)
{
p = p.link;
}
p.x = p.first;
}
Try this:
public void blah() {
Node p = first;
while (p.link != null) {
p = p.link;
}
p.link = first;
}
Be aware that this will create a circular list, that's what you intend, right? Also, I'm assuming that first is an attribute of the class where blah() resides.
This would do the job for you.
public void blah(Node list){
Node firstNode = list;
while (list.link != null){
list = list.link;
}
list.link = firstNode;
}
The 'first' reference you've used in the code suggests that its a member variable. If you want to read more on Singly Linked lists in Java thoroughly, follow this link.

Sorted linked list implementation

i am a novice programmer, to be specific, i am learning java programming and i am supposed to implement sortedLinkedList class that extends LinkedList class from the java library. The list has to store persons in ascending order of their surnames. I have already written my Person class that implements Comparable interface. my problem is, I have been struggling implementing this sortedLinkedClass but to no avail. My code runs without any compiling or run time error but the program does not print anything. Another thing as you can see , I am testing it with Integers instead of Persons and it throws NullPointerException when trying to add a number that is already in the list. My code is as it is below.
import java.util.*;
public class SortedLinkedList< E> extends LinkedList<E>
{
private Link<E> first;
private Link<E> last;
/**
* Constructor for objects of class SortedLinkedList
*/
public SortedLinkedList()
{
//super();
first = null;
last = null;
}
/*
* Link class for creating Link nodes in the SortedLinkedList objects
*/
private class Link<E>
{
public Comparable<E> data;
public Link next;
}
/*
* Overiding add method from LinkedList class
*/
public boolean add(E obj)
{
Link newLink = new Link();
newLink.data = (Comparable<E>)obj;
// When the list is initially empty
if (first == null)
{
first = newLink;
last = newLink;
return true;
}
// When the element to be added is less than the first element in the list
if (newLink.data.compareTo(first.data) < 0)
{
//newLink.data = obj;
newLink.next = first;
first = newLink;
return true;
}
// When the element to be added is greater than every element in in list
// and has to be added at end of the list
if (newLink.data.compareTo(last.data) > 0)
{
//newLink.data = obj;
last.next = newLink;
last = newLink;
return true;
}
//When the element to be added lies between other elements in the list
if (newLink.data.compareTo(first.data) >= 0 && newLink.data.compareTo(last.data) <= 0)
{
//newLink.data = obj;
Link current = first.next;
Link previous = first;
while (newLink.data.compareTo(current.data) <= 0)
{
previous = current;
current = current.next;
}
previous.next = newLink;
newLink.next = current;
}
return true;
}
public static void main (String[] args)
{
LinkedList<Integer> list = new SortedLinkedList<Integer>();
list.add(4);
list.add(5);
list.add(10);
list.add(9);
//list.add(5);
ListIterator<Integer> iterator = list.listIterator();
while (iterator.hasNext())
{
System.out.println(iterator.next());
}
}
}
If you must use a LinkedList, all you really have to do is override the "add" method so that it inserts your element in the correct position. You can do that by invoking the add(integer,Object) method which inserts your element in a specific position.
Here's a quick and dirty (and non-generic :P) implementation of what I'm talking about.
public class PersonLinkedList extends LinkedList<Person> {
public boolean add(Person personToAdd) {
int index = 0;
for( ; index<size() ; index++){
Person personAlreadyInList = get(index);
if(personToAdd.compareTo(personAlreadyInList) < 0){
break;
}
}
add(index, personToAdd);
return true;
};
public static void main(String[] args) {
Person amy = new Person("Amy");
Person bob = new Person("Bob");
Person claire = new Person("Claire");
PersonLinkedList list = new PersonLinkedList();
list.add(bob);
list.add(claire);
list.add(claire);
list.add(amy);
list.add(bob);
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Person person = (Person) iterator.next();
System.out.println(person);
}
}
}
class Person implements Comparable<Person>{
private String name;
public Person(String name) { this.name = name; }
public String getName() { return name; }
#Override
public String toString() { return getName();}
#Override
public int compareTo(Person p) {
return name.compareTo(p.name);
}
}
The reason nothing gets printed is because you store the data in your own linked list data tree and not the LinkedList's data tree. You don't override the iterator method, so the iterator will loop through LinkedList's data which is empty. This is also a problem with all the other methods in LinkedList.
Are you sure you need to inherit from the LinkedList class or are you suppose to make your own class.
If you are supposed to inherit from LinkedList get rid of you node and use LinkedList for storing the data. Your add method would then use a ListIterator to find the correct spot for adding and use the add method of ListIterator.
If you don't inherit from LinkedList then extend AbstractSequentialList.
Note:
Both of these options should not be used in real code. Adding automatic sorting breaks the List interface.
The whole problem is a perfect example of "prefer composition over inheritance".
If this is homework do it as instructed, otherwise I'd recommend changing the exercise to implement a SortedCollection backed by a LinkedList. Then implement Collection and use a List as a member variable.
You could use a SortedSet if you don't need to support elements with the same sort key.
Also, the reason your code doesn't print anything is because you override adding items to the list, but not iterating (the iterator() or listIterator() methods.) Extending LinkedList doesn't automagically make your data structure iterable unless you modify its contents using the base class add(), remove(), and other methods.
besides iterator, add/remove override, I think your algorithm to sort is not correct. And that leads to the nullpointer exception when you add existing elements into your "sortedLinkedList".
while (newLink.data.compareTo(current.data) <= 0)
{
previous = current;
current = current.next;
}
I think what you wanted is while (newLink.data.compareTo(current.data) >0) . not <=0. here is the mistake.
since "=0" is in while condition, it will go through the whole list, till the last element, then execute:
(current is the last now)
previous = current;
current = current.next; (now, current is Null, since last.next is Null)
finally, current is Null, then comes again, current = current.next; Bang! Nullpointer.
so I guess the Nullpointer was thrown at this line.

Categories