remove at index linked list - java

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

Related

What's wrong with sorted set code? My output should match sample

Can anyone help on what's wrong with my code? Only the first input number shows up when I run it (it doesn't create a sorted list), the delete command isn't working, and the 'true' 'false' in exists command doesn't show up. My output should match the given sample I put at the end.
The areas I had to fill in to make the code work are the areas after the TODOTODOTODO symbols which would be 44-61, 75-83, 97-105. I'm not sure where I went wrong in those areas and why it is not working correctly to give the desired output?
import java.util.Scanner;
// Defines the a Sorted Set collection and implements a driver program in main
public class SortedSet {
// Define a basic element of a linked list
private class LinkedNode {
int x; // Value stored in the node
LinkedNode next; // Reference to the next node in the list
}
LinkedNode front = null; // Reference to the front of the singly linked list
// Adds the integer x to the collection.
// The resulting collection is sorted in increasing order and
// does not contain any duplicate values.
public void add(int x) {
// Initialize a new node to be added to the collection
LinkedNode newNode = new LinkedNode();
LinkedNode cur = front;
newNode.x = x;
// Check if list is empty
if (cur == null) {
front = newNode;
}
// If list is not empty, check if node should be placed in front
else if (front != null) {
if (newNode.x < front.x) {
newNode.next = front;
front = newNode;
}
// If not in front, check for the middle or the end, or duplicate.
else {
// <TODO><TODO><TODO>
LinkedNode temp = cur;
LinkedNode prev = cur;
int middle = x;
while (temp != null) {
if(temp.x > newNode.x) {
middle = 1;
newNode.next = temp;
prev.next = newNode;
}
prev = temp;
temp = temp.next;
}
if (middle == 0) {
prev = newNode;
}
}
}
}
// Deletes the integer x from the sorted set.
// The remaining collection remains sorted and without duplicates.
public void delete(int x){
// Declare a new reference and initialize it to the front of the list
LinkedNode cur = front;
// Check if list is empty
if (front == null) {
System.out.print("There is nothing to delete!");
} else { // Not empty
// Go through list, checking whether node is in the list, and delete if found
// <TODO><TODO><TODO>
LinkedNode prev = new LinkedNode();
while (cur.x != x && cur != null) {
prev = cur;
cur = cur.next;
}
if (cur != null)
prev.next = cur.next;
}
}
// Returns true if the integer x exists in the sorted set and false otherwise.
public void exists(int x) {
// Declare a new reference and initialize it to the front of the list
LinkedNode cur = front;
// Check if list is empty.
if (front == null) {
System.out.println("false");
}
// If not empty, check for the node.
// <TODO><TODO><TODO>
else {
while (cur != null) {
if (cur.x==x)
return;
cur=cur.next;
}
return;
}
}
// Returns a string representing the sorted set as a space separated list.
public String toString() {
String s = "";
LinkedNode cur = front;
while (cur!=null) {
s+= cur.x + " ";
cur = cur.next;
}
return s;
}
// Driver method
public static void main(String[] args) {
// Declare variables
SortedSet sortedSet = new SortedSet();
Scanner scan = new Scanner(System.in);
String[] tokens;
String command;
int num;
// Print header info
System.out.println("Programming Fundamentals\n"
+ "NAME: Andres Reyes\n"
+ "PROGRAMMING ASSIGNMENT 4\n");
// Enter command loop
while (true) {
// Prompt the user for a command
System.out.print("Enter command: ");
String input = scan.nextLine();
// Parse input
if (input.equals("q")) break; // user quits
tokens = input.split("\\s");
if (tokens.length < 2) continue; // invalid input
command = tokens[0];
num = Integer.parseInt(tokens[1]);
// Execute command
if (command.equals("add")){
sortedSet.add(num);
System.out.println(sortedSet);
} else if (command.equals("del")) {
sortedSet.delete(num);
System.out.println(sortedSet);
} else if (command.equals("exists")) {
sortedSet.exists(num);
} else {
System.out.print("Command does not exist");
}
}
System.out.println("\nGood bye!");
}
}
I made following changes in the add-function and they got it working for me:
// If not in front, check for the middle or the end, or duplicate.
else {
// <TODO><TODO><TODO>
LinkedNode temp = cur.next; // start at cur.next as your temp-variable
LinkedNode prev = cur;
int middle = 0; // set middle to 0
while (temp != null) {
if(temp.x > newNode.x) {
middle = 1;
newNode.next = temp;
prev.next = newNode;
}
prev = temp;
temp = temp.next;
}
if (middle == 0) {
// add node to the end
prev.next = newNode;
}
}
}
You have to start at cur.next as your temp-variable.
As far as I can see, you're not yet checking if there are any duplicate values in your list.
Edit: I didn't work on the exists-method, which is not giving you any output at the moment. The problem is simply that you're generating any output while you're checking if a value exists in your list. You could either write a System.out.print which prints "true" in case the value was found or "false" in case if wasn't. Or you change the return type of the exists-function to boolean, return a boolean according to the result and print the return value.
It might also help you to visualize a linked list to unterstand why you have to change the temp-variable to cur.next. I think https://www.tutorialspoint.com/data_structures_algorithms/linked_lists_algorithm.htm gives a good explaination of the insertion process.
I can give you some hints. The main problem I see with this code is that you really need a reference to the start of the LinkedList (the head) would be the only way to print the list and check for duplicates.
The following should be added to your class
LinkedList head = null; //start of the list
Then you have to update your toString() or you will never print the correct elements in your list no matter what you do. Try this:
public String toString(){
StringBuilder output = new StringBuilder();
LinkedNode current = head;
while(current != null){
output.append(current.x).append(" ");
current = current.next;
}
return output.toString();
}
You have to be really careful when you are appending to a String in a loop because Strings are immutable. Everytime you are appending to a list you are creating a new String. Instead, use StringBuilder.
//s+= cur.x + " ";
Your add method should handle the following cases:
Case 1: List is empty: ( don't forget to set ref to head)
Case 2: new element is great than front of list
Case 3: new element is less than current head
Case 4: new element is less than current and greater than head

Removing an element by index in a linked list

A method for removing an element from a linked list has been implemented:
public void remove(T e) {
Node<T> node = first;
Node<T> prevNode = null;
while(node != null){
if(e.equals(node)){
if(prevNode == null) {
first = node.next;
}
else {
prevNode.next = node.next;
}
size--;
}
else {
prevNode = node;
}
node = node.next;
}
}
How to correctly implement deleting an element by index? Using the capabilities of the remove method.
public void removeByIndex(int i) {
remove(i);
}
Something like this should work:
public void remove(int i) {
if (i >= size || i < 0) {
throw new ArrayIndexOutOfBoundsException();
}
Node<T> remove;
if (i == 0) {
remove = first;
first = first.next;
first.prev = null; // <- For double linked list
} else {
Node<T> node = first;
for (int j = 0; j < i - 1; ++j) {
node = node.next;
}
remove = node.next;
if (i == size - 1) {
node.next = null;
} else {
node.next.next.prev = node; // <- For double linked list
node.next = node.next.next;
}
}
// Clear links from removed Node
remove.next = null;
remove.prev = null; // <- For double linked list
size--;
}
Find the node before position i. Point that node to the "over next" node.
Edit
The original code example was a rough sketch at best. Updated with a more complete version.
Edit #2
Slight improvements:
Clears links from the removed node
Also handles double linked lists
remove(get(i));
This is not the most efficient solution, but a simple one which uses the remove(T) method. You call it with get(i) as the object to be removed - which is the element at the specified index.
Note: This solution has some issues if the list has duplicate values, but in that case you shouldn't use the remove(T) method anyway. If you want it to be safe, iterate to the specified index:
Node<T> node = first;
for(int i=0;i<index;i++){
prevNode=node;
node=node.next;
}
and do this:
node.prev.next=node.next;
node.next.prev=node.prev;
size--;
Of course, this is just a rough implementation. To ensure full compability, you should check if the index is valid and use the unlink(Node) method of LinkedList.
The LinkedList also has an implementation for the remove(int) method:
checkElementIndex(index);
return unlink(node(index));

Method to delete object from Linked list

I do not see my mistake, correct me, please!
I need to delete an object from Linkedlist. But I got an error NPE in if (current.item.equals(e))
public void remove(T e) {
if (first == null) {
throw new IndexOutOfBoundsException("List is empty");
}
if (first.item.equals(e)) {
first = first.next;
first.next.prev = null;
}
if (last.item.equals(e)) {
last = last.prev;
last.prev.next = null;
} else {
Node<T> current = first;
for (int a = 0; a < size; a++) {
current = current.next;
if (current.item.equals(e)) {
current.prev.next = current.next;
current.next.prev = current.prev;
}
}
size--;
System.out.println("Removed");
}
}
Linkedlist<String> list = new Linkedlist<>();
list.put("Maria");
list.put("Ales");
list.put("zina");
list.put("bina");
list.put("fina");
list.remove("zina");
Some issues:
Your code is too optimistic. There are several boundary cases you should check for null values.
The code blocks that deal with a match of the first or last node, rewire the wrong node.
The size value is not adjusted when the first or last node is removed
When no match is found, size is still decremented.
Corrected version with comments:
public void remove(T e) {
if (first == null) {
throw new IndexOutOfBoundsException("List is empty");
}
if (first.item.equals(e)) {
first = first.next;
// first can be null now!
if (first != null) {
// As you already moved the `first` reference, you should not go to next:
first.prev = null;
}
} else if (last.item.equals(e)) { // make this an else if
last = last.prev;
// As you already moved the `last` reference, you should not go to prev:
last.next = null;
} else {
Node<T> current = first.next; // can go to next here already
// avoid current to be null, so make it the loop condition
while (current) {
if (current.item.equals(e)) {
current.prev.next = current.next;
current.next.prev = current.prev;
// No need to continue. Just exit here
break;
}
current = current.next;
}
if (current == null) return; // Not found! We should not decrement the size
}
// Size must be decremented here, since it also applies to head/tail removals!
size--;
System.out.println("Removed");
}
Remarks:
After last = last.prev; we can be sure that last is not null. If it were, then the original value of last was equal to first, and then we would never have gotten here.
In the if (current.item.equals(e)) { block, we can be sure that both current.prev and current.next are not null. If they would have been, then current would represent the first/last node, for which we had already concluded that they were not a match.
I assumed that all nodes are guaranteed to have an item property.
I assumed that at most one node should be removed

Remove all occurrences of item from a Linked List

I've been working on this lab assignment for a few hours and can't understand why this code is not working. The question is to add the method int removeEvery(T item) that removes all occurrences of item and returns the number of removed items to a link list class that implements a link list interface.
This is my code: It removes some occurrences of the item, but not all of them.
public int removeEvery(T item){
int index = 0;
Node currentNode = firstNode;
for(int i = 1; i <= numberOfEntries; i++)
{
System.out.println(currentNode.getData());
if (item.equals(currentNode.getData())){
index++;
remove(i);}
else{
currentNode = currentNode.getNextNode();}
}
if(index != 0)
return index;
return -1;
}
Here is the remove method that was included in the LinkList class:
public T remove(int givenPosition)
{
T result = null; // return value
if ((givenPosition >= 1) && (givenPosition <= numberOfEntries))
{
assert !isEmpty();
if (givenPosition == 1) // case 1: remove first entry
{
result = firstNode.getData(); // save entry to be removed
firstNode = firstNode.getNextNode();
if (numberOfEntries == 1)
lastNode = null; // solitary entry was removed
}
else // case 2: givenPosition > 1
{
Node nodeBefore = getNodeAt(givenPosition - 1);
Node nodeToRemove = nodeBefore.getNextNode();
Node nodeAfter = nodeToRemove.getNextNode();
nodeBefore.setNextNode(nodeAfter); // disconnect the node to be removed
result = nodeToRemove.getData(); // save entry to be removed
if (givenPosition == numberOfEntries)
lastNode = nodeBefore; // last node was removed
} // end if
numberOfEntries--;
} // end if
return result; // return removed entry, or
// null if operation fails
} // end remove
There is something special with your linked list, you can access next element with current.getNextNode but you delete using the element index. You should look in the rest of your implementation how this index is managed. Does the first element have index 0 or 1 (you start your loop with 1). What happens to the indexes of all elements when you remove one. Do the elements know their index ?
You could use something like
int deletedNodes = 0;
int currentIndex = 0; // check if 1 or 0
currentNode = fist;
while(currentNode != null){ // I guess lastNode.getNextNode() is null
if(//should remove){
remove(currentIndex);
deletedNodes++
// probably no need to change the index as all element should have been shifted back one index
} else {
currentIndex++; // index changes only if no node was deleted
}
currentNode = currentNode.getNextNode(); // will work even if it was deleted
}
return deletedNodes;
I think the problem you have comes from remove(i).
When you remove the i-th element, the i+1-th element becomes the i-th and so on: every element is shifted. Therefore if you need to remove 2 elements in your list that are at index j and j+1, removing the j-th element calling remove(j) will shift the j+1-th element at the index j. Hence removing that second element requires calling remove(j) again, and not remove(j+1).
So you need to decrement i after removing.
Since your remove method actually decrements numberOfEntries, the condition on your while loop is properly updated. So all you need to do is replace
if (item.equals(currentNode.getData())) {
index++;
remove(i);
}
else {
currentNode = currentNode.getNextNode();
}
by
if (item.equals(currentNode.getData())) {
index++;
remove(i--);
}
// update the current node, whether removing it or not
currentNode = currentNode.getNextNode();
Iterator.remove()
This problem you are describing shows the usefulness of Iterator.remove() when using data structures from the JDK for going through an iterable collection and removing elements as you go through it.
After removing a node, as #Vakimshaar suggested, you need to decrement the i because the node at this index has been removed and there is a new node at the same index. In addition to that, you also need to update the currentNode reference as it would still be pointing to the node you've just removed, but it should really be pointing to the new node that has moved to this index.
So in the if (item.equals(currentNode.getData())){ block you need to do the following:
Node nextNode = currentNode.getNextNode();
index++;
remove(i--);
currentNode = nextNode;
With this, your code should correctly remove all occurrences.
Here is a Java Code to delete all occurrences of an item from a linked list :
public class LinkedList{
Node head;
class Node{
int data;
Node next;
Node(int d){data =d; next = null;}
}
public void push(int new_data){
Node new_node = new Node(new_data);
new_node.next = head;
head = new_node;
}
public void insertAfter(Node givenNode, int new_data){
if(givenNode == null)
System.out.println("Given node cannot be empty");
Node new_node = new Node(new_data);
new_node.next = givenNode.next;
givenNode.next = new_node;
}
public void append(int new_data){
Node new_node = new Node(new_data);
if(head == null)
head = new_node;
else{
Node last = head;
while(last.next != null)
last = last.next;
last.next = new_node;
}
}
public void printList(){
Node temp = head;
while(temp != null){
System.out.println(temp.data + " ");
temp = temp.next;
}
}
void deleteNode(int key){
// Store head node
Node temp = head, prev=null;
// If head node itself holds the key or multiple occurrences of key
while(temp != null && temp.data == key){
head = temp.next;
temp = head;
}
// Delete occurrences other than head
while(temp != null){
// Search for the key to be deleted, keep track of the
// previous node as we need to change 'prev.next'
while(temp != null && temp.data != key){
prev = temp;
temp = temp.next;
}
// If key was not present in linked list
if(temp == null) return;
// Unlink the node from linked list
prev.next = temp.next;
//Update Temp for next iteration of outer loop
temp = prev.next;
}
}
public static void main(String[] args){
LinkedList llist = new LinkedList();
llist.push(6);
llist.append(7);
llist.append(7);
llist.append(7);
llist.append(9);
llist.push(10);
llist.deleteNode(7);
llist.printList();
}
}
Output :
10
6
9

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