Remove method for LinkedList - java

So, I am trying to write two overloaded remove methods for LinkedList class, where one takes an index of an element that needs to be removed and another one that takes Object that needs to be removed. But when I try to make a LinkedList of integer and call the latter method, method that takes in index is called instead. Is there any way around this??
(PS. I know you can just change the name of the method, but I am given an interface file that requires me to write overloaded methods)
public E remove(int index) {
for (int i = 0; i < index;i++) {
curNode = curNode.next();
}
if (curNode == head && curNode == tail) {
head = null;
tail = null;
}
else {
URNode sucNode = curNode.next();
URNode prevNode = curNode.prev();
if (sucNode != null)
sucNode.setPrev(prevNode);
else {
prevNode.setNext(null);
tail = prevNode;
}
if (prevNode != null)
prevNode.setNext(sucNode);
else {
sucNode.setPrev(null);
head = sucNode;
}
}
numElements--;
return null;
}
public boolean remove(Object o) {
URNode curNode = head;
for (int i = 0; i < numElements;i++) {
if (curNode.element() == o) {
remove(i);
return true;
}
curNode = curNode.next();
}
return false;
}
public static void main(String args[]){
LinkedList intList = new LinkedList();
intList.add(1);
intList.add(2);
intList.add(3);
intList.remove(1); //I want this to remove node with element 1, instead of node with index of 1
//[2][3] should be returned, not [1][3]
}

intList.remove(Integer.valueOf(1)); // just make it Integer but not int

Related

Issue sorting LinkedList with Item object

I have an issue creating a sort() method for my linked list.
This is my implementation of Comparable in the Item class.
public class Item implements Comparable <Item>{
public Date delivered;
public final String RFIDNR;
public String name;
}
public int compareTo(Item other)
{
return name.compareTo(other.getItemName());
}
This is my sort method in my linked list class
public void sort()
{
Node node = header.next;
Node tempNode = null;
boolean sorted = false;
while (!sorted)
{
sorted = true;
while (node != null)
{
if (node.itm.compareTo(node.next.itm) > 0) throw new NullPointerException();
{
tempNode = node.next;
node.next = node;
node = tempNode;
sorted = false;
}
node = node.next;
}
}
}
What i try to do here is change position of elements that are not in ascending order and switch them. Going through the whole list until sorted = true.
I am running into NullPointerException errors.
Any help is much appreciated.
Look at the following code.
while (node != null) {
if (node.itm.compareTo(node.next.itm) > 0) throw new
NullPointerException();
{
You don't check to see if node.next is null so you try to compare to something that isn't there when trying to access node.next.itm.
I can't guarantee a specific solution since you didn't post your implementation but you need to also ensure node.next is not null. Try the following:
while (node != null) {
if (mode.next != null && node.itm.compareTo(node.next.itm) > 0) {
//do the swapping
}
Solved it using the following.
for (int i = 0; i < size; i++)
{
Node node = header.next;
Item temp = null;
while (node.next != null) {
if (node.itm.compareTo(node.next.itm) > 0)
{
temp = node.next.itm;
node.next.itm = node.itm;
node.itm = temp;
}
node = node.next;
}
}

LinkedList from scratch, replacing a node

I was given an assignement to create a LinkedList from scratch, I've figured how to code a method that add a node at the end of the list but I still can't figure how to replace a node. Here is what I have so far:
public boolean replace(int element, int index) {
Node temp= new Node(pElement);
Node current = getHead();
if (!isEmpty()) {
for (int i = 0; i < index && current.getNext() != null; i++) {
current = current.getNext();
}
temp.setNext(noeudCourant.getNext());
noeudCourant.setNext(temp);
listCount++;
return true;
}
return false;
}
Using aNode.replace(10, 4) on "0 1 2 3 4 5 6 7 8 9 10"
will make it into
[0]->[1]->[2]->[3]->[4]->[10]->[5]->[6]->[7]->[8]->[9]->[10]
but I want:
[0]->[1]->[2]->[3]->[10]->[5]->[6]->[7]->[8]->[9]->[10]
Any help is appreciated.
[edit]I already have a working method setData() but the assignment I have forbid me to use it. What I want is basically this:
http://i.imgur.com/oOVYCvc.png
Here is a simple solution for your question:
package linkedlist;
class Node {
public Node next = null;
public int element;
public Node(int el) {
element = el;
}
}
class LinkedList {
public Node first = null;
public void add(Node node) {
if (first == null) {
first = node;
} else {
// Traverse to the last
Node cursor = first;
while (cursor.next != null) {
cursor = cursor.next;
}
cursor.next = node;
}
}
public void add(int[] elements) {
int len = elements.length;
for (int i=0;i < len;i++) {
add(new Node(elements[i]));
}
}
public boolean replace(int element, int index) {
Node cursor = first;
Node prev = null;
while (cursor != null && index >= 0) {
index--;
prev = cursor;
cursor = cursor.next;
}
if (index > 0) return false;
if (prev != null)
prev.element = element;
return true;
}
public void displayAll() {
Node cursor = first;
while (cursor != null) {
System.out.print(cursor.element + " ");
cursor = cursor.next;
}
System.out.println();
}
}
public class Main {
public static void main(String[] args) {
// Prepare elements
LinkedList linkedList = new LinkedList();
linkedList.add(new int[]{0,1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
println("Display the initial linked list content:");
linkedList.displayAll();
println("After replace:");
linkedList.replace(10, 4);
linkedList.displayAll();
println("Done");
}
static void println(String msg) {
System.out.println(msg);
}
}
If you really want to replace the Node and do not delete it then here is how you should be writing your replace() function:
public boolean replace(int element, int index) {
Node head = getHead();
int counter = 0;
while(null != head && counter++ < index - 1) {
head = head.getNext();
}
if(null == head || null == head.getNext()) return false;
Node newNode = new Node(element);
newNode.setNext(head.getNext().getNext());
head.setNext(newNode);
return true;
}
Here, I'm assuming that you have setNext() method in your Node class to set the link.
Also note that here it is assumed that you'll never replace head itself i.e. you'll never replace the element at index 0 or else you'll have to return the new head from the function.
Try below code. I have written the logic in comments wherever required.
public boolean replace(int element, int index) {
Node temp= new Node(pElement);
Node current = getHead();
if (!isEmpty()) {
//Run for loop one less than index value.
for (int i = 0; i < index -1 && current.getNext() != null; i++) {
current = current.getNext();
}
// At this point current points to element 3.
// Set next element of node 4 as a next element of new element 10.
temp.setNext(current.getNext().getNext());
// at this point we have two references for element 5 like below
// [0]->[1]->[2]->[3]->[4]->[5]->[6]->[7]->[8]->[9]->[10]
// [10]->[5]->[6]->[7]->[8]->[9]->[10]
// Set null to next element of of element 4 to remove reference to
// element 5
current.getNext().setNext(null);
// At this point we have two list as below:
// [0]->[1]->[2]->[3]
// [10]->[5]->[6]->[7]->[8]->[9]->[10]
// Set new element as next of current element (current element is 3)
current.setNext(temp);
// here we have replaced the element 4 with element 10
listCount++;
return true;
}
return false;
}

Java Iterator Not Working With Single Iterable Object

I am having a problem with Iterators. I am writing a custom linked list as using an iterator to be able to traverse the list.
The iterator looks like this:
public class NodeIterator implements Iterator<Node> {
private Node current = head;
private Node lastReturned = head;
public boolean hasNext() {
return lastReturned.getLink() != null;
}
public Node next() {
lastReturned = current;
current = current.getLink();
return lastReturned;
}
public void remove() {
removeNode(lastReturned);
lastReturned = null;
}
}
I'm still in the early stages so I'm testing the data structures from the console by populating the nodes with this method.
private static void MethodToPopulateNodes() {
MyObject o = new MyObject();
String[] responses = new String[prompts.length];
scanner = new Scanner(System.in);
boolean done = false;
String s = null;
while (!done) {
int i = 0;
for (String prompt : prompts) {
System.out.println(prompt);
s = scanner.nextLine();
if (s.equalsIgnoreCase("stop")) {
done = true;
break;
} else {
responses[i] = s;
}
i++;
}
if (done) {
break;
}
o = new MyObject(responses);
myNode.add(c);
}
}
When I try to use the iterator when there is only one Node, it doesn't do anything. No errors or anything. However, if I have multiple nodes, this foreach works flawlessly.
public static void main(String[] args) {
myNode = new Node();
methodToPopulateLinkedList();
for (Node node : myNode) {
//toString is overridden for my object
System.out.println(node.getData().toString());
}
}
UPDATE: I edited the iterator to return hasNext() == true on the first iteration:
public class NodeIterator implements Iterator<Node> {
private boolean done = false;
private Node current = head;
private Node lastReturned = head;
public boolean hasNext() {
if (head == tail && head != null && !done) {
done = true;
return true;
}
return lastReturned.getLink() != null;
}
public Node next() {
lastReturned = current;
current = current.getLink();
return lastReturned;
}
public void remove() {
removeNode(lastReturned);
lastReturned = null;
}
}
I feel like that is super janky but it works. It seems like Java calls hasNext() first before calling next so I have to treat the special case differently.
|123
hasNext() == true
next() == 1
1|23
hasNext() == true
next() == 2
12|3
Where | equals the cursor. Is that accurate? Is there a better way to solve this?
If there's just one Node, it would have the special case of its ->next being null. Before the loop, try printing out the first node, I think your loop might be looking one ahead.

LinkedList - loop not working - Java

I am required to write a method that returns a number - the amount of times an element is found in a linked list. So far I have;
package Question4;
import net.datastructures.Node;
public class SLinkedListExtended<E> extends SLinkedList<E> {
// returns the number of occurrences of the given element in the list
public int count(E elem) {
Node<E> cursor = tail;
int counter = 0;
if ((cursor != null) && (!(cursor.getElement().equals(elem)))) { //tail isnt null and element is not equal to elem
cursor = cursor.getNext(); //go to next node
} else if ((cursor != null) && (cursor.getElement().equals(elem))){ //cursor isn't null and element equals elem
counter++; //increment counter
}
else {
return counter; //return counter
}
return counter;
}
public static void main(String[] args) {
SLinkedListExtended<String> x = new SLinkedListExtended<String>();
x.insertAtTail("abc");
x.insertAtTail("def");
x.insertAtTail("def");
x.insertAtTail("xyz");
System.out.println(x.count("def")); // should print "2"
x.insertAtTail(null);
x.insertAtTail("def");
x.insertAtTail(null);
System.out.println(x.count("def")); // should print "3"
System.out.println(x.count(null)); // should print "2"
}
}
I have extended to a class which compiles correctly, so I know the problem is in my method. I can't figure out what to do, my code returns 0, which is probably the counter integer remaining at 0 and not going through the loop statement. Any ideas are appreciated.
Edit. SLinkedList code:
import net.datastructures.Node;
public class SLinkedList<E> {
protected Node<E> head; // head node of the list
protected Node<E> tail; // tail node of the list (if needed)
protected long size; // number of nodes in the list (if needed)
// default constructor that creates an empty list
public SLinkedList() {
head = null;
tail = null;
size = 0;
}
// update and search methods
public void insertAtHead(E element) {
head = new Node<E>(element, head);
size++;
if (size == 1) {
tail = head;
}
}
public void insertAtTail(E element) {
Node<E> newNode = new Node<E>(element, null);
if (head != null) {
tail.setNext(newNode);
} else {
head = newNode;
}
tail = newNode;
size++;
}
public static void main(String[] args) { // test
SLinkedList<String> list = new SLinkedList<String>();
list.insertAtHead("lol");
}
}
Maybe you should use a while loop instead of an if clause
**while** ((cursor != null) && (!(cursor.getElement().equals(elem)))) {
The code in count is not in a loop, so it'll just return after the first element.
Try this:
public int count(E elem) {
Node<E> cursor = tail;
int counter = 0;
while (true)
{
if ((cursor != null) && (!(cursor.getElement().equals(elem)))) { //tail isnt null and element is not equal to elem
cursor = cursor.getNext(); //go to next node
} else if ((cursor != null) && (cursor.getElement().equals(elem))){ //cursor isn't null and element equals elem
counter++; //increment counter
}
else {
return counter; //return counter
}
}
}
Also, note that cursor.getElement().equals(elem) will return a NullPointerException when cursor.getElement() is null. The easiest way to deal with this is probably to write a separate equals method:
boolean equals(E e1, E e2)
{
if (e1 == null)
return e2 == null;
if (e2 == null)
return false;
return e1.equals(e2);
}
Also, presumably Node<E> cursor = tail; makes it point to the end of the list and presumably you want Node<E> cursor = head; instead.
One of the fundamental things that you were missing was a loop. Since you are essentially searching for something, you want to loop through the entire list. Once you run into an element that matches the one that you are searching for, you want to increment the count by 1. Once you have finished looping through the entire list, you want to return that count. So this is my solution. I keep it simple so you could understand:
import java.util.LinkedList;
public class Duplicates<E> extends LinkedList<E> {
public static void main(String[] args) {
Duplicates<String> duplicates = new Duplicates<String>();
duplicates.add("abc");
duplicates.add("def");
duplicates.add("def");
duplicates.add("xyz");
System.out.println(duplicates.duplicateCount("def"));
duplicates.add(null);
duplicates.add("def");
duplicates.add(null);
System.out.println(duplicates.duplicateCount("def"));
System.out.println(duplicates.duplicateCount(null));
}
public int duplicateCount(E element) {
int count = 0;
for (E e : this) {
if (e == element) {
count++;
}
}
return count;
}
}
Output:
2
3
2
I suggest you combine Martin's answer (which tells you how to count the elements) with this, which tell you how to be able to use foreach - you just have to make your SLinkedListExtended implement Iterable, whioch should be something liek the follwoing (you could do this on SLinkedList, but I'm assuming you were told not to alter the code for that one):
public class SLinkedListExtended<E> extends SLinkedList<E> implements Iterable<E> () {
public Iterator<E> iterator() {
final Node<E> itHead = head;
return new Iterator<E>() {
Node<E> current = itHead;
long position = 0;
public boolean hasNext() {
return current != null && position < size;
}
public E next() {
current = current.getNext();
++position;
return current.getElement();
}
public void remove() {
throw new UnsupportedOperationException("Not supported yet.");
}
};
}
};
I can't vouch for all the details, but this should cover most of it. You may also consider using equals instead of ==, but don't forget to check the elements for nullity.
next should only be called if hasNext is true, so it's not a problem if it throws an exception (but it should be a NoSuchElementException to keep in line with the contract).
Implementing Iterable makes your class compatible with the Collections library, hence the support for foreach, but you can use it to do raw iteration by calling iterator, hasNext and next yourself.

circular single linkedList

I've done some exercises in Java and now I'm stuck at such a problem - my list works incorrectly. I am sure that remove works incorrectly and maybe you can help me (with advice or code) to implement a circular singly linked list in a correct way. I am not sure whether other functions work properly, but I've tried to do my best.
Here is my code:
import java.util.*;
public class Node {
private Object value;
private Object nextValue;
private Node next;
public Node(int data) {
this.value = data;
this.next = null;
}
public Object getValue() {
return this.value;
}
public Node nextItem() {
return this.next;
}
public void setNextItem(Node nextItem) {
this.next = (Node) nextItem;
this.next.setValue(nextItem.getValue());
}
public void setValue(Object arg0) {
this.value = arg0;
}
}
-------------------------------------------------------------------
import java.util.*;
public class CircularList {
private Object[] array;
private int arrSize;
private int index;
private Node head;
private Node tail;
public CircularList() {
head = null;
tail = null;
}
public boolean add(Node item) {
if (item == null) {
throw new NullPointerException("the item is null!!!");
}
if (head == null) {
head = item;
head.setNextItem(head);
arrSize++;
return true;
}
Node cur = head;
while(cur.nextItem() != head) {
if(cur.getValue() == item.getValue()) {
throw new IllegalArgumentException("the element already " +
"exists!");
}
cur = cur.nextItem();
}
head.setNextItem(item);
item.setNextItem(head);
arrSize++;
return true;
}
public Node getFirst() {
return head;
}
public void insertAfter(Node item, Node nextItem) {
if ((item == null) || (nextItem == null)) {
throw new NullPointerException("the item is nul!!!");
} else if (this.contains(nextItem) == true) {
throw new IllegalArgumentException("the item already exists!");
}
Node cur = head;
while(cur.nextItem() != head) {
if(cur.getValue() == item.getValue()) {
nextItem.setNextItem(item.nextItem());
item.setNextItem(nextItem);
} else {
cur = cur.nextItem();
}
}
}
public boolean remove(Node item) {
if(item == head) {
Node cur = head;
for(int i = 0; i < arrSize-1; i++) {
cur = cur.nextItem();
}
head = head.nextItem();
for(int i = 0; i < arrSize; i++) {
cur = cur.nextItem();
}
arrSize--;
return true;
}
Node cur = head;
int counter = 0;
while(cur.nextItem() != head) {
if(cur == item) {
item = null;
cur = cur.nextItem();
while(cur.nextItem() != head) {
cur.setNextItem(cur.nextItem().nextItem());
}
return true;
}
cur = cur.nextItem();
}
return false;
}
public int size() {
return arrSize;
}
public boolean contains(Object o) {
if ((o == null) && (arrSize == 0)) {
return false;
}
Node cur = head;
while(cur.nextItem() != head) {
if(cur.getValue() == o) {
return true;
}
cur = cur.nextItem();
}
return false;
}
}
Many of these algorithms could be simpler.
Example:
public boolean remove(Node item) {
Node current = head;
for(int i = 0; i < size; i++) {
if (current.getNext() == item) {
current.next = current.getNext().getNext();
size --;
return true;
}
current = current.getNext()
}
return false;
}
There are a variety of issues here beyond the list. You seem to be comparing your nodes with ==. This code will output 'no match'.
Node n1 = new Node(5);
Node n2 = new Node(5);
if (n1 == n2)
System.out.println("objects match");
else
System.out.println("no match");
In add(), it looks like you can only ever have two items in the list, so
head.setNextItem(item);
item.setNextItem(head);
should be this:
cur.setNextItem(item);
item.setNextItem(head);
There's a lot going on in your code, here's some advice for some of it:
In your Node class: Java naming conventions: the same way that setters should be prefixed with "set," getters should be prefixed with "get:" nextItem() should really be getNextItem().
Also in your Node class: as far as I know, the "next value" field of a node of a linked list is usually a reference to the next Node in the list, and should therefore be of type Node, not just any Object. It should work the way you have it, but using explicit typing is a lot safer. (Please correct me if using "Object" is indeed a common way to construct the next node of a linked list.)
In the first case of remove(), when removing the head: you're looping through the list to reach the last value, presumably to reset its "next value" to the new head, but you're not actually doing it. You want something like this:
if (item == head) {
head = head.nextItem();
for(int i = 0; i < arrSize-1; i++){
cur = cur.nextItem();
}
}
cur.setNextItem(head);
I'm not sure what you hope to accomplish with the second loop.
In the second case of remove(): I'm not sure what you're trying to do with the second while loop - reset all the links in the whole list? The whole point of a linked list is to make that unnecessary. Deleting a node in a linked list does not actually get rid of the object (so you don't have to set item to null). Rather, you simply "go around" the unwanted object and "ignore" it, effectively removing it from the list, as in:
Original list:
[ Value: A; Next: B ] --> [ Value: B; Next: C ] --> [ Value C; Next: D ] ...
After deleting node B:
[ Value: A; Next: C ] --> [Value C; Next: D ] ...
[ Value: B; Next: C ] still exists in memory, but nothing is pointing to it, so it will be removed in the next garbage collection cycle.
To implelement: As you walk the list, keep a reference to the previous node that you visited. Then, once you find the item you're looking for (using correct comparison, as Thomas noted), you can simply set prev.setNextItem(cur.nextItem()); (caveat: untested code):
Node prev = head;
Node cur;
while ((cur = prev.nextItem()) != head) {
if (cur.equals(item)) {
prev.setNextItem(cur.getNextItem());
return true;
}
}
I hope these tips help you along the correct path.

Categories