POP method linked list - java

I've implemented a pop method in Java I would use it for delimiter matching, though it leaves one element in the list.
public int length(){
Node current = this.head;
int length = 0;
while(current != null){
current = current.getNextNode();
length += 1;
}
return length;
}
public char pop(){
Node current = this.head;
Node lastN = this.last;
for(int i = 0; i < length() - 2; i++){
current = current.getNextNode();
}
current.setNextNode(null);
this.last = current;
return lastN.getBracket();
}
How do I pop the first element if length is >= 1?, or any suggestion for improving my code.

Use java.util.LinkedList.
With addFirst(), addLast(), size(), removeFirst() and removeLast() you are covered.
Alternatively, check this delimiter check example for another way.
In you code, you miss the "initial" or "last element" case, which is special. You should check for the case of this.head == this.last; case where you should return the last element and clean up the list.

Why moving through the list elements in the loop? How about instead of that:
if (this.head != null)
{
char val = this.head.getBracket();
this.head = this.head.getNextNode();
}
This snippet will drop the first element and set head to point to the second element. I guess JVM will delete old head. If the list is circular, then also set last to point to the new head.

Related

Using ListIterator to get the Next and Previous elements from the Current element of the List

I have list of element for that I have to match some specified element and get the previous and next for that element.
The problem here is when you do iterator.next() or iterator.prev() it returns the same element because the cursor is moved back and forth returning to the same element. So what I did is I use previousIndex() and nextIndex() method to get only index and retrieve element from the list from that index.
Also make sure to do decrement from previous index as cursor is moved to next element so current element will be returned.
for (final ListIterator<Xyz> iterator = nodeList.listIterator();iterator.hasNext();){
if(iterator.next().equals(midString.get())) {
final Xyz prev=nodeList.get(iterator.previousIndex()-1);
final Xyz next= nodeList.get(iterator.nextIndex());
return some condition true;
}
}
Wanted to know is there any better approach to achieve same or any improvements in existing solution.
If you need to process previous, current and next nodes at each iteration step, you can simply define a couple local variables before the loop.
The idea of utilizing ListIterator will not improve the readability, conversely to make the ListIterator approach working you have to introduce a lot of redundancy because each call of next() or previous() advances the iterator, and it'll also cause unnecessary performance overhead.
That's how it can be done by maintaining two variables for previous and current nodes.
public static boolean processNodes(List<Node> nodeList) {
if (nodeList.size() < 3) return false;
Node prev = nodeList.get(0); // previous node
Node cur = nodeList.get(1); // current node
for (int i = 2; i < nodeList.size(); i++) {
Node next = nodeList.get(i); // next node
if (cur.equals(something) && someSondition(prev, next)) {
return true; // or introduce a flag (before the loop), set the flag to true and break from the loop
}
prev = cur; // reassigning nodes
cur = next;
}
return false;
}
I would also suggest introducing a boolean flag initialized to false and change it value to true in the loop, rather than returning from the middle of the method.
public static boolean processNodes(List<Node> nodeList) {
boolean result = false;
if (nodeList.size() < 3) return result;
Node prev = nodeList.get(0); // previous node
Node cur = nodeList.get(1); // current node
for (int i = 2; i < nodeList.size(); i++) {
Node next = nodeList.get(i); // next node
if (cur.equals(something) && someSondition(prev, next)) {
result = true;
break;
}
prev = cur; // reassigning nodes
cur = next;
}
return result;
}

Why can't I remove occurrences in the linked list?

Problem: Given a value, remove all instances of that value from a linked list. More info below: JAVA
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode n = head; //1, 2, 6, 3, 4, 5, 6
while(n.next == null){
if(n.next.val == val){
n.next = n.next.next;
}
n = n.next;
if(n == null){break;}
}
return head;
}
}
Since its a pass by reference, it should be updating shouldn't it?
I tried:
removeElements([1,2,6,3,4,5,6], 6)
But it didn't remove anything. So what I am doing incorrectly?
There are a couple of issues:
you want to loop until a node is null not until is not null (i.e. while( ... != null))
you might want to loop until n is null, not until n.next is null, otherwise you'd skip the last element
you want to check for n.val == val not n.next.val == val, otherwise you'd skip the first element
if you check n you want to keep track of the previous node in case you need to remove n, i.e. prev.next = n.next.
if the first element (the head) is to be removed you need to replace the head, i.e. return the second element (this can be done by checking prev == null which would mean that n is the current head).
As mentioned by Thomas in his first point, you wrote the while loop incorrectly. Also, because you have a single linked list, you need to keep track of the previous node (also mentioned by Thomas).
public static ListNode removeElements(ListNode head, int val)
{
ListNode n = head;
ListNode prev = null; //the previous node.
while (n != null)
{
if (n.value == val)
{
//if prev is null it means that we have to delete the head
//and therefore we need to advance the head
if (prev == null)
{
head = n.next;
prev = null;//remains at null because there's nothing before head
n = head;//new head, let's start from here
} else
{
prev.next = n.next; //let's skip the element to delete
n = n.next;//let's advance to the next node
}
} else
{
//nothing to delete, let's advance to the next node and make
//the current node the previous node in the next iteration
prev = n;
n = n.next;
}
}
return head;
}
Its always a good practice to solve these questions with proper test cases. Design the possible test cases including the corner cases. Then follow your algorithm and see if it solves the problem for the test cases. Write the code and dry run it, this will do a sanity check of the code as well as of the logic.
Below are the cases for this question for which test cases must be written.
Null list,
List with one element and value being equal to the value to be deleted
List with one element and value not being equal to the value to be deleted
List with two elements and first node value being equal to the value to be deleted
List with two elements and last node value being equal to the value to be deleted
List with three elements and first node value being equal to the value to be deleted
List with three elements and second node value being equal to the value to be deleted
List with three elements and last node value being equal to the value to be deleted
Below is the code for the problem of removing nodes with a given value in a linked list.
public ListNode removeElements(ListNode head, int val) {
while(head != null && head.val == val){
head = head.next;
}
if(head == null){
return null;
}
ListNode node = head;
while(node.next != null){
if(node.next.val == val){
node.next = node.next.next;
}else{
node = node.next;
}
}
return head;
}

remove at index linked list

Hi im trying to remove a link in part of a linked list but i'm not sure how to remove the link. when i run it the links are still there. im using a junit to test the function if that matters .
Here is what i have so far.
public void removeAt(int k)
{
Node w = first;
int counter = 0;
if (k<0 || k >= size())
{
throw new IndexOutOfBoundsException("Error ");
}
else
{
while (w!= null)
{
counter++;
if (counter == k)
{
Node now = w.next;
w= now.next;
}
w=w.next;
}
}
assert check();
}
Thanks for the help
You need to change a node's .next field in order to remove a node, e.g. w.next = w.next.next removes the w.next node from the list (because nothing is pointing to it anymore); be sure to check for null pointers (if w.next is null then w.next.next will throw an exception). Also, add a break statement to the end of your if block since there's no need to traverse the rest of the list.
if (counter == k){
Node now = w.next;
w.next= now.next;
break;
}
test this.
You are updating a local variable. What you need to do is update the link prior to the current node:
if (k == 0)
{
first = first.next ;
// you also have to free the memory for first.
}
else
{
Node Last = first ;
w = first.next ;
counter = 1 ;
while (w!= null)
{
counter++; // Not sure your conventions, but I think this should be at the end
if (counter == k)
{
last.next = w.next ; /// happily skipping w :)
// remember you have to free w
break ; // no point in continuing to the end.
}
w=w.next;
}
}
}
You always need to keep track of the previous node. And also what if the node that's to be deleted is the first node? I guess you need to change the while block to look something like:
Node l = first;
while (w!= null)
{
if (counter == k)
{
if (w == first)
first = w.next;
else
l.next = w.next;
w.next = null;
break;
}
l=w;
w=w.next;
counter++;
}
Check the following code that remove the element from linked list,
public void delete(T element){
if(head != null){ // first check your header node is null or not
// create two references of your linked list
Node<T> tmp = head; // it will hold current value
Node<T> tmp1 = head.getNextRef(); // it will hold next value
while(true){ // iterate through whole linked list
if(head.getValue() == element){ // if you found element at first place
head = head.getNextRef(); // then point head to next node of it
break;
}
if(tmp1.getValue()==element){ // to remove node refer to next of tmp1
tmp.setNextRef(tmp1.getNextRef());
break;
}else{
tmp = tmp1;
tmp1 = tmp1.getNextRef();
if(tmp1==null)
break;
}
}
}
}

Java : singly linked list, dummy node, insert

public class A<E> extend AbstractList<E>{
private SLNode<E> Head = new SLNode<E>
private int length = 0; // length of the list
// I will skip the class of SLNode<E>
// Head's element and successor is initialized as null in the class SLNode<E>
public void add(int index, E element) // insert an element in the list
{
// if index is less than 0 or greater than the length
if( (index < 0) || (index > length ) )
throw new IndexOutOfBoundsException();
if(index ==0)
{
SLNode<E> newnode = new SLNode<E>(element, null); // make new node
newnode.setSuccessor(Head.getSuccessor());
Head.setSuccessor( newnode);
length++;
}
}
Q1. Is this right way of adding element at the front of the list? (using dummy header node, but no tail)
Q2. Would it be the same whether the list is empty or non-empty?
That's not a bad way to do it, though using a "dummy" node for "head" is somewhat unusual.
But it has the advantage that you can replace "Head" with "current", initialize that to "Head", then "crawl" up the list index nodes and do your insert, and you wouldn't have to special-case the zero case.
public void add(int index, E element) // insert an element in the list
{
// if index is less than 0 or greater than the length
if( (index < 0) || (index > length ) ) {
throw new IndexOutOfBoundsException();
}
// Find insertion point
SLNode<E> current = Head;
for (int i = 0; i < index; i++) {
current = current.getSuccessor();
}
// Create & insert new node
SLNode<E> newnode = new SLNode<E>(element, null);
newnode.setSuccessor(current.getSuccessor());
current.setSuccessor( newnode);
length++;
}
(But note that standard naming convention is to reserve names with initial upper-case for class names.)
Assuming that this is your insert at head method, I dont understand why you need to pass index in. Ideally I would like to have just 1 method for insert. But since you are specfically asking for insert at head.
public void addToHead(E element) // insert an element at head
{
if(length==0)
throw new Exception("head does not exist");
element.setSuccessor(head);
head = element;
length++;
}
I don't think you really need to have a special case for inserting at the front of the list. Inserting at the front of this list is no different from inserting anywhere else in the list.
public void add(int index, E element)
{
// if index is less than 0 or greater than the length
if ((index < 0) || (index > length))
throw new IndexOutOfBoundsException();
SLNode<E> previousNode = head;
for ( int i = 0; i < index; i++ ) {
previousNode = previousNode.getSuccessor();
}
SLNode<E> newNode = new SLNode<E>(element, previousNode.getSuccessor());
previousNode.setSuccessor(newNode);
length++;
}
Basically, this just traverses the list to find the correct node to insert after - if the index is 0, it immediately stops at head. Once you have the node to insert after, you perform these three steps:
Create a new node and set its successor to the successor of the previous node
Set the successor of the previous node to be the new node
Add one to the length of the list
I ran a couple little tests on this and it seemed to work just fine.
Note that this approach pretty much assumes that head will never actually be considered an element in the list. It's really just a place to start the list. By that, I mean that head.getElement() will always return null - it's not really part of the list. I'm not sure if that's the implementation you wanted, but it seemed to make the most sense when you said that you start the list with a head element, even when the list is supposed to be empty.
Q1. Is this right way of adding element at the front of the list?
(using dummy header node, but no tail)
EDIT: After rereading your question, and trying your code, I would say yes.
Q2. Would it be the same whether the list is empty or non-empty?
EDIT: Yes, it appears to work on an empty list.
dummy_header_list<String> theList = new dummy_header_list<String>();
System.out.println(theList);
theList.add(0,"first add");
System.out.println(theList);
theList.add(0,"second add");
System.out.println(theList);
theList.add(0,"third add");
System.out.println(theList);
gives:
[]
[first add]
[second add,first add]
[third add,second add,first add]
with this toString:
public String toString()
{
String output = "[";
SLNode<E> temp = Head.getSuccessor();
while ( temp != null ) {
if ( output.length() == 1 ) {
output = output + temp.toString();
}
else {
output = output + "," + temp.toString();
}
temp = temp.getSuccessor();
}
output = output + "]";
return output;
}

Java: NPE in Circular Linked List :(

import javax.swing.JOptionPane;
public class RotateArrayCircularLL
{
private Node head=null;
public void init()
{
int choice = 0;
while (choice != -1){
choice = Integer.parseInt(JOptionPane.showInputDialog("Enter -1 to stop loop, 1 to continue"));
if(choice == -1)
break;
inputNum();
}
printList();
}
public void inputNum()
{
Node n;
Node temp;
int k;
k = Integer.parseInt(JOptionPane.showInputDialog(null,"Enter a number:"));
n = new Node(k);
if (head == null) {
head = n;
} else {
temp = head;
while (temp.getNext() != null)
temp = temp.getNext();
temp.setNext(n);
}
}
public void printList()
{
Node temp = head;
int count = Integer.parseInt(JOptionPane.showInputDialog("Enter the value to shift to the right"));
for (int i = 1; i <= count; i++) // Rotates the head
temp = temp.getNext();
for (Node c = temp; c != null && c.getNext() != head; c= c.getNext()){ // Prints the new LL
System.out.print(c.getInfo());
}
}
}
I get an NPE during the second for loop. I understand that it is giving me a NPE because I reach the end of the list, but how can I stop it from doing this?
It appears from the behavior you are seeing that one of the nodes in your linked list is returning null instead of the next element of the list. At a guess, I'd suggest that the last node of your list is probably not pointing to the first node of your list. Hence as Hovercraft Full Of Eels suggests, you don't really have a properly circular linked list. If you can post the code showing how temp is populated, it may be possible to give a more concrete solution to your issue. Otherwise, you need to treat the case where getNext() returns null as a special case and ensure that you instead get the first element from the initial list.

Categories