removing element from LinkedList - java

I'm trying to remove the last node from a linkedList and return it. This is part of a Linkedlist class. The following method that I wrote doesn't delete the last node. Does anybody know why?
public int delete(){
if(front==null){
throw new NoSuchElementException();
}else{
ListNode current = front;
while(current.next!=null){
current = current.next;
}
int delete = current.data;
current = null;
return delete;
}
}

Setting current to null only changes the reference to null. It in no way affects the linked list data structure. You need to find the second to last node and set its next pointer to null:
int data = secondToLastNode.next.data;
secondToLastNode.next = null;
return data;
Of course, you'll need to handle the situation where there is only one node in the list which the above code doesn't account for.

You are only setting your local reference current to null; you're not changing your list.
Assuming this is a singly linked list, you will need to set the second-to-last ListNode's next to null (or set front to null if it's the only item).

There are three situations you need to cover:
There are no entries in your list. Usually you just exit in this case but throwing an exception like you do should be fine.
There is only one entry in your list. In this case your variable front will have a value but front.next will be null. You should set front to null in this case.
For none of the above you should set the next of the last but one entry to null. You have not managed to do this yet.

I wound up explaining this here.
Jave is a pass-by-reference language and = reassigns the reference. You're only changing local references, see sample code in above link and understand that.

Remember the 'current' before the one that has the null pointer, and set the 'next' pointer of that node to null. That way, you delete the reference to the latest node, instead of just updating a local variable.

Try this one
public int delete(){
if(front==null){
throw new NoSuchElementException();
} else if(front.next===null){
return front.data;
}else{
ListNode current = front;
while(current.next.next!=null){
current = current.next;
}
int deleted_node = current.next.data;
current.next = null;
return deleted_node;
}
}

Related

To delete an entire linked list in java which I have created

I want to delete an entire list which I have created in java(note: I am not using internal list in java.util). I have assigned head to null but my question is will the java garbage collector handle the list which has no head or should I delete every node(I mean setting every node to null) which will be handled by java garbage collector? Following is my code, please let me know which one is ok although both works but I would still like to know. Thanks in advance.
//first code
public void deleteList()
{
Node n = head;
Node n1;
head = null;
System.out.println("Deleting list");
while(n != null)
{
n1 = n;
n = n.next;
n1 = null;
}
n1 = n;
n1 = null;
System.out.println("List deleted");
}
//second code
public void deleteList()
{
head = null;
}
It depends on your implementation. If your Node class is internal only (so you don't ever return a Node where it might be saved) and you don't hold any in statics, then there should be no path to any node from a garbage collection root and GC will get rid of them.
So it's probably right, unless your implementation is doing something unusual. (I'm also assuming you don't have a tail variable or anything else that references an internal Node, because those would also need to be set to null).
The Garbage Collector will destroy an object only when the particular object doesn't have any linked internal dependency to other nodes. In other words, whenever the objects are not referenced anymore, they are destroyed and their memory is reclaimed.
your first code is right, when you have internal dependency with other nodes i.e, tail node, for example.
your second is right, when you doesn't have any dependency with other node.

Why can't I use method return as a pointer in Java?

Solved, thanks. I actually added head.next to my head.child's last node, so the next run of lastNode returned different pointer.
In the following code, the commented code gave different result, why?
I was expecting the same behavior.
Node p = lastNode(head.child); //Define a extra pointer
p.next = head.next;
if(head.next!=null) head.next.prev = p;
//lastNode(head.child).next = head.next; // Not Working
//head.next.prev = lastNode(head.child);
This has nothing to do with Java. In the first example you call lastNode once and store the result in p. In your second example, you call lastNode twice, but after the first call, you add a new last node to your list, so the return value is different the second time!
The second calculation of lastNode(head.child) after you change lastNode(head.child).next gives you the new last node. You must keep a pointer to the old last node in order to update the prev of the new last node.

Setting Head in a Linked List

I am trying to make a Linked List I have a working insert method however I don't know how to set head to the front of the list.
public void insert(Object o) {
curr = new Link(o,curr);
if(ticker ==0){
head = curr;
tail = curr;
}
ticker++;
}
This just sets head to the end of the list when it needs to be in the front. Any help would be much appreciated. And if you need anything else to figure this out let me know.
I don't exactly know what your Link is, but I think you should create a Node class like
class Node {
Object value;
Node next;
Node pre; // optional
}
And your head and tail will be a instance of Node.
I think your problem lies in the constructor for Link. Based on your result, the new Link stores a reference to the old Link; this is reversed, and thus your list is built in reverse. Set the Link argument's next node to the Link being instantiated, something like
public Link(Object value, Link previous) {
...
previous.nextLink = this;
...
}
The head of a linked list refers to the first element that was added, not the last, as you indicated in your comment. That's just the terminology.
You need an else branch in your insert method setting tail = current, so you always have a reference to the end of the list. (head already points to the beginning of the list, and which node is the head won't change) In fact, if you do this, you won't even need the variable tail, since current will serve the same purpose.

Reversing a doubly-linked list with dummy nodes by using 'head.next' as a start point instead of 'head'

First and foremost, I have a working implementation of a reverse() method and I'm not looking for help on how to do it as it is a homework question. My problem is an error I ran into doing what I thought would save an iteration on my while loop by starting with the first real element in the list, rather than the head dummy node.
The working reverse() method code:
public void reverse() {
Node<T> current = head;
Node<T> temp = null;
tail = head;
while(current != null) {
temp = current.prev;
current.prev = current.next;
current.next = temp;
current = current.prev;
}
head = temp.prev;
}
And an example of the program with which it belongs to running into the error:
https://ideone.com/KKUtMn
The change that breaks my program:
Node<T> current = head.next;
Making that change causes a NullPointerException on any calls to addLast(x) after a call to reverse() is made. The call to reverse() reverses the list without error or issue and I can call addFirst(x) just fine, but the first call to addLast(x) will throw the exception. I find it especially odd because the call to addLast(x) uses the tail dummy node to insert the element, but the only usage of tail in reverse() is assigning it prior to the loop and shouldn't be affected by whatever current gets referenced to.
The reason I thought I'd make the change is because that first iteration on head seemed useless when it just got reassigned to temp.prev after the while loop anyway. I didn't need the traversal offered by the loop either since I could simply point directly to the first non-dummy node from the start. I'm obviously wrong as the idea doesn't work, but I can't figure out the logic that makes that so.
Any ideas?
The problem is that you still set tail = head in the beginning. Since you never reverse the prev and next of your previous head, it will not HAVE a prev, only a next. Which causes the NullPointerException when you call addLast and he tries to get the prev of the tail ;)
You could move to the end of the list
while(current.next != null){
current = current.next;
if you are at the end, you start to swap the node's next reference...
current.next = curr.prev
and so on

Binomial Heap Insertion java

I'm having trouble inserting into a binomial heap, When I call insert 1 it prints (1) and then I insert 2 it displays (2) instead of (1(2)) and then three it displays (3) instead of (3)(1(2)). I would be very grateful if someone could help figure out my problem. Thank you in advance. Here is my code
public class BHeap {
int key;
int degree;//The degree(Number of children)
BHeap parent, leftmostChild, rightmostChild, rightSibling,root,previous,next;
public BHeap(){
key =0;
degree=0;
parent =null;
leftmostChild=null;
rightmostChild=null;
rightSibling=null;
root=null;
previous=null;
next=null;
}
public BHeap merge(BHeap y){
BHeap newHeap = new BHeap();
BHeap currentHeap = y;
BHeap nextHeap = y.rightSibling;
while(currentHeap.rightSibling !=null){
if(currentHeap.degree==nextHeap.degree){
if(currentHeap.key<nextHeap.key){
if(currentHeap.degree ==0){
currentHeap.leftmostChild=nextHeap;
currentHeap.rightmostChild=nextHeap;
currentHeap.rightSibling=nextHeap.rightSibling;
nextHeap.rightSibling=null;
nextHeap.parent=currentHeap;
currentHeap.degree++;
}
else{
newHeap = currentHeap;
newHeap.rightmostChild.rightSibling=nextHeap;
newHeap.rightmostChild=nextHeap;
nextHeap.parent=newHeap;
newHeap.degree++;
nextHeap.rightSibling=null;
nextHeap=newHeap.rightSibling;
}
}
else{
if(currentHeap.degree==0){
nextHeap.rightmostChild=currentHeap;
nextHeap.rightmostChild.root = nextHeap.rightmostChild;//add
nextHeap.leftmostChild=currentHeap;
nextHeap.leftmostChild.root = nextHeap.leftmostChild;//add
currentHeap.parent=nextHeap;
currentHeap.rightSibling=null;
currentHeap.root=currentHeap;//add
nextHeap.degree++;
}
else{
newHeap=nextHeap;
newHeap.rightmostChild.rightSibling=currentHeap;
newHeap.rightmostChild=currentHeap;
currentHeap.parent= newHeap;
newHeap.degree++;
currentHeap=newHeap.rightSibling;
currentHeap.rightSibling=null;
}
}
}
else{
currentHeap=currentHeap.rightSibling;
nextHeap=nextHeap.rightSibling;
}
}
return y;
}
public void Insert(int x){
BHeap newHeap= new BHeap();
newHeap.key=x;
if(this.root==null){
this.root=newHeap;
}
else{
this.root = merge(newHeap);
}
}
public void Display(){
System.out.print("(");
System.out.print(this.root.key);
if(this.leftmostChild != null){
this.leftmostChild.Display();
}
System.out.print(")");
if(this.rightSibling!=null){
this.rightSibling.Display();
}
}
}
When you are inserting, you are making a new BHeap object and then passing that to merge(). Your new BHeap has no rightSibling, so you skip the entire while loop and just return the new BHeap. So the new BHeap becomes the root of the whole BHeap and you throw out what was there before.
Update: I'm not going to write pseudo-code because it's right there in your code.
So you make a new BHeap and Insert(1). Your Insert method makes a second new BHeap and then checks the root of the current BHeap. That's null, so the second BHeap becomes the root. That's fine.
Now you Insert(2). Again, create another BHeap. This time the root of the current BHeap is not null so we call merge passing in the new BHeap. Note that this new BHeap is now referred (inside merge) as y. Also note that you have done nothing to this new BHeap aside from setting the key field so all other fields are null.
Inside merge you make yet another BHeap object, and make another reference currentHeap that refers to y. (Again, only the key field has been set so all other fields are null.) You refer to y's rightSibling as nextHeap and then comes the while loop. The while loop says that while the rightSibling of currentHeap is not null, do a bunch of stuff.
But as I've said above, everything about currentHeap (aka y aka the brand new BHeap you created in Insert) is null. So the entire while loop is skipped and you return y from merge.
Insert then accepts the return value from y and sets that as the root of the current BHeap. The old root is discarded and sits in the corner weeping bitterly at its sad fate before the garbage collector comes along and shuffles it into an early grave. The new root cheers triumphantly and reigns supreme, the king of the BHeap (and the only member of the BHeap)... until you call Insert(3).
And you? You learn how to use a debugger.
In your method merge you pass a BHeap object y. You do change anything as the BHeap object you have created and passed to merge in your insert method does not add any siblings. The while loop is never run.
Also, I think you may want to review your merge method. It seems you do not ever take into account the current BHeap that you are merging into and simply reformat the given BHeap argument.

Categories

Resources