Custom LinkedList: remove method does not work as expected - java

I'm implementing the remove() method of a custom LinkedList class, but it does not remove any items from the list, and I can't figure out why.
Here's how I do it:
public void remove(int position) {
if (position < 0 || position >= size) {
throw new IndexOutOfBoundsException(
"position should be beween 0 and size - 1");
}
Cell current = top;
for (int i = 0; i < position; i++) {
current = current.next;
}
current = current.next.next;
size--;
}
This method tries to remove an item between 2 nodes (removing first node and last node cases are ignored).
This is the test case I am executing, and after trying to remove the element with index 2, it still prints the hole list:
CustomList<String> list = new CustomList<String>();
list.add("Hello");
list.add("morena");
list.add("What");
list.add("Miranda");
list.add("Aston");
list.remove(2);
list.printAll();
For completion, here's the full implementation of the list:
public class CustomList<T> {
private class Cell {
T data;
Cell next;
public Cell(T data) {
this.data = data;
}
}
private Cell top;
private int size;
public void add(T data) {
addAtEndInOn(data);
size++;
}
/**
* adds an item at the end of the list in O(n) by iterating the whole list
* before adding the node
*/
private void addAtEndInOn(T data) {
if (top == null) {
top = new Cell(data);
} else {
Cell current = top;
while (current.next != null) {
current = current.next;
}
current.next = new Cell(data);
}
}
public void remove(int position) {
if (position < 0 || position >= size) {
throw new IllegalArgumentException(
"position should be a positive number");
}
Cell current = top;
for (int i = 0; i < position; i++) {
current = current.next;
}
current = current.next.next;
size--;
}
public void printAll() {
Cell current = top;
while (current != null) {
System.out.println(current.data);
current = current.next;
}
}
}

current = current.next.next changes nothing in your list.
In order to remove an element, you need to write :
current.next = current.next.next;
This would remove the element that is next to the current element. It that's not the element you meant to remove, you should change the for loop so that it stops when current is the element before the one you want to remove.
Make sure to test that current.next is not null, to avoid NullPointerException.

You have to break the link, not just change the position of current. The link is represented by current.next

Related

Insert a node at a specific position in a linked list JAVA

public static SinglyLinkedListNode insertNodeAtPosition(SinglyLinkedListNode llist, int data, int position) {
if(llist == null) {
llist = new SinglyLinkedListNode(data);
return llist;
} else {
for (int i = 0; i < position-1; i++) {
llist = llist.next;
}
SinglyLinkedListNode temp = llist;
llist.next = new SinglyLinkedListNode(data);
llist = llist.next;
llist.next = temp.next;
return llist;
}
}
This is my code to place a custom index node in LinkedList. But hackerrank is not accepting my code. What's wrong with my algorithm?
The problem is that your code always returns the newly created node, but you should always return the first node in the list, which either is what it was when you got it, or is the new node in case the position was zero.
What to look at:
I'll not provide the corrected code, but will give you two hints:
By moving llist ahead in the for loop, you lose the reference to that first node, so use a different variable for walking through the list.
Also, you should deal specifically with the case where position is 0, as this is the only case where the returned value is not the original llist value, but the new node's reference, much like you have in the if block.
Easiest solution No need of explaination :
Solution :
static SinglyLinkedListNode insertNodeAtPosition(SinglyLinkedListNode head, int data, int position) {
if (head == null) return null;
SinglyLinkedListNode temp = new SinglyLinkedListNode(data);
if (position == 0) {
temp.next = head;
return temp;
}
SinglyLinkedListNode p = head;
for (int i = 0; i< position-1; i++) {
p = p.next;
}
SinglyLinkedListNode next = p.next;
p.next = temp;
temp.next = next;
return head;
}
The problem requires you to return a linked list. When we are asked to return a linked list, actually we return the first node of the linked list.
So, your problem is the returned value in your code script is not the first node of the linked list.
The simplest solution is that you keep the first node in another variable, and
return that variable after you have done the insert thing.
for example:
SinglyLinkedListNode dumyNode = llist;
......
return dumyNode;
Suppose given the correct Node class, you can try this approach (without index collision case):
private Node find(int index) {
Node curr = head;
for (int i = 0; i < index; i++)
curr = curr.next;
return curr;
} // end find()
public Object get(int index) throws IndexOutOfBoundsException {
if (index >= 0 && index < size) {
Node curr = find(index);
return curr.data;
} else {
throw new IndexOutOfBoundsException();
} // end if - else
} // end get()
public void add(Object data, int index) throws IndexOutOfBoundsException {
if (index >= 0 && index < size + 1) {
if (index == 0)
head = new Node(data);
else {
Node prev = find(index - 1);
prev.next = new Node(data);
} // end if - else
size++;
} else {
throw new IndexOutOfBoundsException();
} // end if - else
} // end add()

How to write a remove method with Cyclic Doubly-Linked-List with Generic Nodes in Java

I am implementing a cyclic DoublyLinkedList data structure. Like a singly
linked list, nodes in a doubly linked list have a reference to the next node, but unlike a singly linked list, nodes in a doubly linked list also have a reference to the previous node. Additionally, because the list is "cyclic", the "next" reference in the last node in the list points to the first node in the list, and the "prev" reference in the first node in the list points to the last node in the list.
I am having trouble with my remove method with some size usage. It's the message I'm getting when I run my tests.
Here's my code:
public class DoublyLinkedList<E>
{
private Node first;
private int size;
#SuppressWarnings("unchecked")
public void add(E value)
{
if (first == null)
{
first = new Node(value, null, null);
first.next = first;
first.prev = first;
}
else
{
first.prev.next = new Node(value, first, first.prev);
first.prev = first.prev.next;
}
size++;
}
private class Node<E>
{
private E data;
private Node next;
private Node prev;
public Node(E data, Node next, Node prev)
{
this.data = data;
this.next = next;
this.prev = prev;
}
}
#SuppressWarnings("unchecked")
public void add(int index, E value)
{
if (first.data == null)
{
throw new IndexOutOfBoundsException();
} else if (index == 0)
{
first = new Node(value, first.next, first.prev);
}
else
{
Node current = first;
for (int i = 0; i < index - 1; i++)
{
current = current.next;
}
current.next = new Node(value, current.next, current.prev);
}
}
Here is the method I need help with.
The remove method should remove the element at the specified index in the list. Be sure to address the case in which the list is empty and/or the removed element is the first in the list. If the index parameter is invalid, an IndexOutOfBoundsException should be thrown.
#SuppressWarnings("unchecked")
public void remove(int index)
{
if (first.data == null)
{
throw new IndexOutOfBoundsException();
}
else if (index == 0)
{
first = first.next;
}
else
{
Node current = first.next;
for (int i = 0; i < index - 1; i++)
{
current = current.next;
}--size;
current.next = current.next.next;
}
}
Here is the rest of the code. The get method is incorrect, but I asked that in a different question.
public E get(int index)
{
if(index >= size)
{
}
return null;
//return first.data;
}
#SuppressWarnings("unchecked")
public int indexOf(E value)
{
int index = 0;
Node current = first;
while (current != current.next)
{
if (current.data.equals(value))
{
return index;
}
index++;
current = current.next;
}
return index;
}
public boolean isEmpty()
{
if (size == 0)
{
return true;
}
else
{
return false;
}
}
public int size()
{
return size;
}
This was not easy at all, however I did find the answer to my question. This is a cyclic doubly linked list. Here it is:
#SuppressWarnings("unchecked")
public void remove(int index)
{
if(index < 0 || index > size)
{
throw new IndexOutOfBoundsException();
}
Node n = first;
for(int i = 0; i < index; i++)
{
n = n.next;
}
// n points to node to remove
n.prev.next = n.next;
n.next.prev = n.prev;
if (index == 0)
{
if(size == 1)
{
first = null;
}
else
{
first = first.next;
}
}
size--;
}

How to create a get Method with nodes off a generic type in java

I am implementing a cyclic DoublyLinkedList data structure. Like a singly linked list, nodes in a doubly linked list have a reference to the next node, but unlike a singly linked list, nodes in a doubly linked list also have a reference to the previous node.
Additionally, because the list is "cyclic", the "next" reference in the last node in the list points to the first node in the list, and the "prev" reference in the first node in the list points to the last node in the list.
I need help starting my get method, I've been looking around and I couldn't find anything that could help me since I am working with a Generic Type . I need to return E and every other examples show me it with int as an example. Here is my code:
public class DoublyLinkedList<E>
{
private Node first;
private int size;
#SuppressWarnings("unchecked")
public void add(E value)
{
if (first == null)
{
first = new Node(value, null, null);
first.next = first;
first.prev = first;
}
else
{
first.prev.next = new Node(value, first, first.prev);
first.prev = first.prev.next;
}
size++;
}
private class Node<E>
{
private E data;
private Node next;
private Node prev;
public Node(E data, Node next, Node prev)
{
this.data = data;
this.next = next;
this.prev = prev;
}
}
#SuppressWarnings("unchecked")
public void add(int index, E value)
{
if (first.data == null)
{
throw new IndexOutOfBoundsException();
} else if (index == 0)
{
first = new Node(value, first.next, first.prev);
}
else
{
Node current = first;
for (int i = 0; i < index - 1; i++)
{
current = current.next;
}
current.next = new Node(value, current.next, current.prev);
}
}
#SuppressWarnings("unchecked")
public void remove(int index)
{
if (first.data == null)
{
throw new IndexOutOfBoundsException();
}
else if (index == 0)
{
first = first.next;
}
else
{
Node current = first.next;
for (int i = 0; i < index - 1; i++)
{
current = current.next;
}
current.next = current.next.next;
}
size--;
}
I can't think of a way to get started on this, but basically what this method should do is return the element at the specified index in the list. If the index parameter is invalid, an IndexOutOfBoundsException should be thrown.
public E get(int index)
{
}
Also, my remove method isn't accurate, but I'll figure that one out myself, I just need help with my get method.
I figured it out, I'm just shocked that I wasn't getting any responses for this question. Either way, I am going to write some comments so it kind of guides future viewers who are struggling with this.
#SuppressWarnings("unchecked")
public E get(int index)
{
if(index < 0) //The index needs to be above 0.
{
throw new IndexOutOfBoundsException();
}
if(index > size) //Since we're going to run a for loop, we need to make sure the index doesn't go past the size of the list.
{
throw new IndexOutOfBoundsException();
}
Node current = first; //We want to create another node to perform this method.
for (int i = 0; i < index; i++) //We are going to set i to 0 and loop around this for loop until we reach the index.
{
current = current.next;
}
return (E) current.data; //Since we are working with generics, we need to return a type E, and it needs to be in parenthesis so it gets that object.
}
Another problem I sort of had was that in my Node Class I had the in there, when I could've moved on without it. Lets update it to be
private class Node
{
private E data;
private Node next;
private Node prev;
public Node(E data, Node next, Node prev)
{
this.data = data;
this.next = next;
this.prev = prev;
}
}
And now my getMethod() will be as follows:
#SuppressWarnings("unchecked")
public E get(int index)
{
if(index < 0)
{
throw new IndexOutOfBoundsException();
}
if(index > size)
{
throw new IndexOutOfBoundsException();
}
Node current = first;
for (int i = 0; i < index; i++)
{
current = current.next;
}
return current.data;
}
You can also use a hash map, and you will get the data on constant time
public T get(int position){
Node<T> node = map.get(position);
T dat = node.getData();
return dat;
}

Removing values from a custom LinkedList class

This custom class mimics the functionality of Java's LinkedList Class except it only takes integers and obviously lacks most of the functionality. For this one method, removeAll(), I am to go through each node for the list and remove all nodes with that value. My problem is that when the first node in the list contains the value to be removed, it then ignores all subsequent nodes that also contain that value. What seems to be the problem? Am I removing the front node the wrong way? For example, [1]->[1]->[1] should return an empty list, but it leaves the front node and I get [1]
edit: it seems to fail to remove the second node instead of the first.
This is the class (Stores ListNodes as a list):
public class LinkedIntList {
private ListNode front; // first value in the list
// post: constructs an empty list
public LinkedIntList() {
front = null;
}
// post: removes all occurrences of a particular value
public void removeAll(int value) {
ListNode current = front; // primes loop
if (current == null) { // If empty list
return;
}
if (front.data == value) { // If match on first elem
front = current.next;
current = current.next;
}
while (current.next != null) { // If next node exists
if (current.next.data == value) { // If match at next value
current.next = current.next.next;
} else { // If not a match
current = current.next; // increment to next
}
}
}
// post: appends the given value to the end of the list
public void add(int value) {
if (front == null) {
front = new ListNode(value);
} else {
ListNode current = front;
while (current.next != null) {
current = current.next;
}
current.next = new ListNode(value);
}
}
// Sets a particular index w/ a given value
public void set(int index, int value) {
ListNode current = front;
for (int i = 0; i < index; i++) {
current = current.next;
}
current.data = value;
}
}
Here is the ListNode class (responsible for a single "node"):
//ListNode is a class for storing a single node of a linked
//list. This node class is for a list of integer values.
public class ListNode {
public int data; // data stored in this node
public ListNode next; // link to next node in the list
// post: constructs a node with data 0 and null link
public ListNode() {
this(0, null);
}
// post: constructs a node with given data and null link
public ListNode(int data) {
this(data, null);
}
// post: constructs a node with given data and given link
public ListNode(int data, ListNode next) {
this.data = data;
this.next = next;
}
}
The [1] element that actually stays in the list is the second element which becomes the front element in your code:
if (front.data == value) { // If match on first elem
front = current.next;
current = current.next;
}
After that you just iterate over the list and remove the matching elements.
Replacing the problematic code with this should do the work:
while (front.data == value) { // If match on first elem
front = front.next;
if (front == null) {
return;
}
}
One of the simplest and cleanest way to remove element from a custom Linked list is as follows.
import java.util.concurrent.atomic.AtomicInteger;
public class LinkedList<T> {
class Node<T> {
private T data;
private Node<T> next;
Node(T data) {
this.data = data;
this.next = null;
}
}
private Node<T> head;
private Node<T> tail;
private AtomicInteger size = new AtomicInteger();
public void add(T data) {
Node<T> n = new Node<T>(data);
if (head == null) {
head = n;
tail = n;
size.getAndIncrement();
} else {
tail.next = n;
tail = n;
size.getAndIncrement();
}
}
public int size() {
return size.get();
}
public void displayElement() {
while (head.next != null) {
System.out.println(head.data);
head = head.next;
}
System.out.println(head.data);
}
public void remove(int position) throws IndexOutOfBoundsException {
if (position > size.get()) {
throw new IndexOutOfBoundsException("current size is:" + size.get());
}
Node<T> temp = head;
for (int i = 0; i < position; i++) {
temp = temp.next;
}
head = null;
head = temp;
size.getAndDecrement();
}
}

java list shift items by rearranging links

I'm working with a linked list in java and I need to take a list of x objects and move the odd positioned objects to the end of the list.
I have to do it by using linking, no new nodes, no list.data exchanges.
I feel like I have a decent handle when I'm moving stuff from one list to another, but traversing and appending with references to only one list is really tough.
Here's the actual question ---
Write a method shift that rearranges the elements of a list of integers by moving to the end of the list all values that are in odd-numbered positions and otherwise preserving list order. For example, suppose a variable list stores the following values:
[0, 1, 2, 3, 4, 5, 6, 7]
The call of list.shift(); should rearrange the list to be:
[0, 2, 4, 6, 1, 3, 5, 7]
you must solve this problem by rearranging the links of the list.
below is the class that I need to write the method before (with the aforementioned restrictions.
I can't really come up with a plan of attack.
// A LinkedIntList object can be used to store a list of integers.
public class LinkedIntList {
private ListNode front; // node holding first value in list (null if empty)
private String name = "front"; // string to print for front of list
// Constructs an empty list.
public LinkedIntList() {
front = null;
}
// Constructs a list containing the given elements.
// For quick initialization via Practice-It test cases.
public LinkedIntList(int... elements) {
this("front", elements);
}
public LinkedIntList(String name, int... elements) {
this.name = name;
if (elements.length > 0) {
front = new ListNode(elements[0]);
ListNode current = front;
for (int i = 1; i < elements.length; i++) {
current.next = new ListNode(elements[i]);
current = current.next;
}
}
}
// Constructs a list containing the given front node.
// For quick initialization via Practice-It ListNode test cases.
private LinkedIntList(String name, ListNode front) {
this.name = name;
this.front = front;
}
// Appends the given value to the end of the list.
public void add(int value) {
if (front == null) {
front = new ListNode(value, front);
} else {
ListNode current = front;
while (current.next != null) {
current = current.next;
}
current.next = new ListNode(value);
}
}
// Inserts the given value at the given index in the list.
// Precondition: 0 <= index <= size
public void add(int index, int value) {
if (index == 0) {
front = new ListNode(value, front);
} else {
ListNode current = front;
for (int i = 0; i < index - 1; i++) {
current = current.next;
}
current.next = new ListNode(value, current.next);
}
}
public boolean equals(Object o) {
if (o instanceof LinkedIntList) {
LinkedIntList other = (LinkedIntList) o;
return toString().equals(other.toString()); // hackish
} else {
return false;
}
}
// Returns the integer at the given index in the list.
// Precondition: 0 <= index < size
public int get(int index) {
ListNode current = front;
for (int i = 0; i < index; i++) {
current = current.next;
}
return current.data;
}
// Removes the value at the given index from the list.
// Precondition: 0 <= index < size
public void remove(int index) {
if (index == 0) {
front = front.next;
} else {
ListNode current = front;
for (int i = 0; i < index - 1; i++) {
current = current.next;
}
current.next = current.next.next;
}
}
// Returns the number of elements in the list.
public int size() {
int count = 0;
ListNode current = front;
while (current != null) {
count++;
current = current.next;
}
return count;
}
// Returns a text representation of the list, giving
// indications as to the nodes and link structure of the list.
// Detects student bugs where the student has inserted a cycle
// into the list.
public String toFormattedString() {
ListNode.clearCycleData();
String result = this.name;
ListNode current = front;
boolean cycle = false;
while (current != null) {
result += " -> [" + current.data + "]";
if (current.cycle) {
result += " (cycle!)";
cycle = true;
break;
}
current = current.__gotoNext();
}
if (!cycle) {
result += " /";
}
return result;
}
// Returns a text representation of the list.
public String toString() {
return toFormattedString();
}
// Returns a shorter, more "java.util.LinkedList"-like text representation of the list.
public String toStringShort() {
ListNode.clearCycleData();
String result = "[";
ListNode current = front;
boolean cycle = false;
while (current != null) {
if (result.length() > 1) {
result += ", ";
}
result += current.data;
if (current.cycle) {
result += " (cycle!)";
cycle = true;
break;
}
current = current.__gotoNext();
}
if (!cycle) {
result += "]";
}
return result;
}
// ListNode is a class for storing a single node of a linked list. This
// node class is for a list of integer values.
// Most of the icky code is related to the task of figuring out
// if the student has accidentally created a cycle by pointing a later part of the list back to an earlier part.
public static class ListNode {
private static final List<ListNode> ALL_NODES = new ArrayList<ListNode>();
public static void clearCycleData() {
for (ListNode node : ALL_NODES) {
node.visited = false;
node.cycle = false;
}
}
public int data; // data stored in this node
public ListNode next; // link to next node in the list
public boolean visited; // has this node been seen yet?
public boolean cycle; // is there a cycle at this node?
// post: constructs a node with data 0 and null link
public ListNode() {
this(0, null);
}
// post: constructs a node with given data and null link
public ListNode(int data) {
this(data, null);
}
// post: constructs a node with given data and given link
public ListNode(int data, ListNode next) {
ALL_NODES.add(this);
this.data = data;
this.next = next;
this.visited = false;
this.cycle = false;
}
public ListNode __gotoNext() {
return __gotoNext(true);
}
public ListNode __gotoNext(boolean checkForCycle) {
if (checkForCycle) {
visited = true;
if (next != null) {
if (next.visited) {
// throw new IllegalStateException("cycle detected in list");
next.cycle = true;
}
next.visited = true;
}
}
return next;
}
}
// YOUR CODE GOES HERE
}
see it this way:
first we need some sort of cursor that will go through the list and point to our "current" node
second we need some boolean variable (i'll call it INV) initialized as FALSE ... everytime we move a node in the list, we invert INV
if you go through the list from the left, the second element is the first to be rearanged, so that will be our initial cursor position
lets take a reference on that element/node, and keep that reference as abort criteria
start of loop:
now remove the current node from the list and insert it at the end of the list (move to the end ... not that the cursor may not move with the node ...)
move the cursor to the node that is right of the former position of the node we just moved (if that exists)
if the current element is our abort criteria (first element we moved) we can assume the list is sorted now in the desired order -> we are finished -> exit the loop ... if it's not our abort criteria ... go on
evaluate "index of the cursor is even" to either TRUE or FALSE ... XOR that with INV
if the result is TRUE move the cursor to the next element ... if it's FALSE remove the node and insert it at the end (move it to the end)
do the loop
--
this approach will not preserve the order while we move through the list, but will have the list in the desired order when it finishes ...
the INV var is for compensation the index shifts when removing a node ... (0,1,2,3 ... if you remove the 1 and put it at the end, 2 will have an odd index, so if we invert that with every move, we get the "right" elements)

Categories

Resources