I'm trying to define a recursive method that removes all instances in the singly-linked list that are equal to the target value. I defined a remove method and an accompanying removeAux method. How can I change this so that if the head needs to be removed, the head is reassigned as well? Here is what I have so far:
public class LinkedList<T extends Comparable<T>> {
private class Node {
private T data;
private Node next;
private Node(T data) {
this.data = data;
next = null;
}
}
private Node head;
public LinkedList() {
head = null;
}
public void remove(T target) {
if (head == null) {
return;
}
while (target.compareTo(head.data) == 0) {
head = head.next;
}
removeAux(target, head, null);
}
public void removeAux(T target, Node current, Node previous) {
if (target.compareTo(current.data) == 0) {
if (previous == null) {
head = current.next;
} else {
previous.next = current.next;
}
current = current.next;
removeAux(target, current, previous); // previous doesn't change
} else {
removeAux(target, current.next, current);
}
}
I prefer to pass a reference to the previous when you remove to switch previous to the next something like this
public void remove(T target){
removeAux(target,head, null);
}
public void removeAux(T target, Node current, Node previous) {
//case base
if(current == null)
return;
if (target.compareTo(current.data) == 0) {
if (previous == null) {
// is the head
head = current.next;
} else {
//is not the head
previous.next = current.next;
}
current = current.next;
removeAux(target, current, previous); // previous doesn't change
} else {
removeAux(target, current.next, current);
}
}
Check this answer graphically linked list may help you to think how to implement it.
If this for training is good but you can do in iterative way.
You could try to fashion your function so that it works like this.
head = removeAux(target, head); // returns new head
A neat trick I learn't from Coursera's Algorithms classes.
The rest of the code is as follows.
public void removeAux(T target, Node current) {
//case base
if(current == null)
return null;
current.next = removeAux(target, current.next);
return target.compareTo(current.data) == 0? current.next: current; // the actual deleting happens here
}
Related
This is the code I was given for the Singly Linked List, however I am struggling on completing the Reverse function. This was the code and my attempt at the reverse function. I keep getting 2 errors that say "Undeclared variable: node" and "imcompatible types: Node cannot be converted to Linkedlist".
class LinkedList
{
Node head;
Node current;
Node previous;
public Object Get()
{
return current != null ? current.GetData() : null;
}
public void Next()
{
if (current != null)
{
previous = current;
current = current.next;
}
}
public void Head()
{
previous = null;
current = head;
}
public void Insert(Object data)
{
Node node = new Node(data);
node.next = current;
if (current == head)
head = node;
else
previous.next = node;
current = node;
}
public void Remove()
{
if (current == null)
throw new RuntimeException("Invalid position to remove");
if (current == head)
head = current.next;
else
previous.next = current.next;
current = current.next;
}
public void Print()
{
for (Head(); Get() != null; Next())
System.out.println(Get());
}
public LinkedList Reverse()
{
Node previous = null;
Node current = node;
Node forward;
while (current != null)
{
forward = current.next;
current.next = previous;
previous = current;
current = forward;
}
return previous;
}
}
There is also class Node:
class Node
{
// Public reference to next node
public Node next;
// Private data field
Object data;
Node(Object data)
{
this.data = data;
}
public Object GetData()
{
return data;
}
}
And this is the main function:
class Test
{
public static void main(String args[])
{
// creating a singly linked list
LinkedList linked_list = new LinkedList();
// adding node into singly linked list
linked_list.Insert(Integer.valueOf(10));
linked_list.Next();
linked_list.Insert(Integer.valueOf(11));
linked_list.Next();
linked_list.Insert(Integer.valueOf(12));
// printing a singly linked
linked_list.Print();
// reversing the singly linked list
linked_list.Reverse();
// printing the singly linked list again
linked_list.Print();
}
}
Here is a simple solution:
public class ListReverser {
public static Node<Integer> reverse(Node head) {
Node current = head;
while(current.getNext() != null) {
Node next = current.getNext();
current.setNext(next.getNext());
next.setNext(head);
head = next;
}
return head;
}
}
I am trying to print the first and last elements in a deque using a toString method however I'm not entirely sure if I am overwriting the toString method correctly.
As far as I can tell, the methods all seem to behave correctly but I have no way of being able to tell as I am unable to see any readable output.
I am aware that there is already a deque interface, however this is part of an exercise in using generics in Java.
This piece of code should create a deque, be able to add values to the front of the deque, remove values from the front, add values to the rear and remove values from the rear.
Here's the class in question:
import java.util.Iterator;
import java.util.NoSuchElementException;
class Deque<T> implements Iterable<T> {
private class Node<T> {
public Node<T> left, right;
private final T item;
public Node(T item) {
if (item == null) {
throw new NullPointerException();
}
this.item = item;
}
public void connectRight(Node<T> other) {
this.right = other;
other.left = this;
}
}
private class DequeIterator implements Iterator<T> {
private Node<T> curr = head;
public boolean hasNext() {
return curr != null;
}
public void remove() {
throw new UnsupportedOperationException();
}
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
T item = curr.item;
curr = curr.right;
return item;
}
}
private Node<T> head, tail;
private int size;
public Iterator<T> iterator() {
return new DequeIterator();
}
public Deque() {
}
public int size() {
return size;
}
public boolean isEmpty() {
return size() == 0;
}
public void checkInvariants() {
assert size >= 0;
assert size > 0 || (head == null && tail == null);
assert (head == null && tail == null) || (head != null && tail != null);
}
public void addFirst(T item) {
Node<T> prevHead = head;
Node<T> newHead = new Node<T>(item);
if (prevHead != null) {
newHead.connectRight(prevHead);
} else {
tail = newHead;
}
head = newHead;
size++;
checkInvariants();
}
public void addLast(T item) {
Node<T> newTail = new Node<T>(item);
Node<T> prevTail = tail;
if (prevTail != null) {
prevTail.connectRight(newTail);
} else {
head = newTail;
}
tail = newTail;
size++;
checkInvariants();
}
public T removeFirst() {
if (isEmpty()) {
throw new java.util.NoSuchElementException();
}
size--;
Node<T> prevHead = head;
head = prevHead.right;
prevHead.right = null;
if (head != null) {
head.left = null;
}
checkInvariants();
return prevHead.item;
}
public T removeLast() {
if (isEmpty()) {
throw new java.util.NoSuchElementException();
}
size--;
Node<T> prevTail = tail;
tail = prevTail.left;
prevTail.left = null;
if (tail != null) tail.right = null;
checkInvariants();
return prevTail.item;
}
#Override
public String toString() {
Node<T> currTail = tail;
Node<T> currHead = head;
head = currHead.right;
tail = currTail.left;
StringBuilder builder = new StringBuilder();
while (currHead != null && currTail != null) {
builder.append(currHead.item + "\n");
}
return builder.toString();
}
public static void main(String[] args) {
Deque<Double> d = new Deque<Double>();
d.addFirst(1.0);
System.out.println(d);
d.addLast(1.0);
//d.removeFirst();
//d.removeLast();
System.out.println(d.toString());
}
}
First of all, you're setting the instance variables head and tail to their respective neighbours, which is definitely not what you're out to do. This leaves your queue in an inconsistent state, where the second element is the head, but it still has a left neighbour, the original head. Same thing for the tail. Generally the toString method shouldn't have side effects.
Neither currTail nor currHead ever change in your while-loop, so your condition currHead != null && currTail != null will always be true if the deque is non-empty. You'd have to set those variables in the loop, however, you don't need to iterate from both ends at once. Iterating from the start will be enough. And then, you can use a for loop, like this:
#Override
public String toString() {
final StringJoiner stringJoiner = new StringJoiner("\n");
for (Node<T> node = head; node != null; node = node.right) {
stringJoiner.add(node.item.toString());
}
return stringJoiner.toString();
}
This sets the variable node to it's right neighbour after every iteration, and if the deque is empty, node will be null from the get-go and the loop will not be entered as is expected.
This is just the more concise (In my opinion) version of this:
#Override
public String toString() {
final StringJoiner stringJoiner = new StringJoiner("\n");
Node<?> node = head;
while (node != null) {
stringJoiner.add(node.item.toString());
node = node.right;
}
return stringJoiner.toString();
}
which is basically your attempt, just fixed.
Not that I've used a StringJoiner instead of a StringBuilder, as it allows you to set a delimeter that is used between each String, which is exactly what you're doing.
I have made my own implementation of a generic Linked Queue for class, it is pretty much finished, here it is:
public class LinkedQueue<T> implements Queue<T> {
//Using head & tail approach.
private myNode<T> head;
private myNode<T> tail;
private int size;
public LinkedQueue(){
this.head = null;
this.tail = head;
this.size = 0;
}
public myNode<T> getterHead(){ //couldn't bring myself to write "get" instead of "getter"
return this.head;
}
#Override
public int size() {
return this.size; //returns number of nodes
}
#Override
public boolean isEmpty() {
return this.head==null;
}
#Override
public void enqueue(T element) {
if(isEmpty()){
this.head = new myNode<T>(element);
this.tail = head;
size++;
}
else{
this.tail.next = new myNode<T>(element);
this.tail = tail.next;
size++;
}
}
#Override
public T dequeue() {
if(isEmpty())throw new NoSuchElementException("This queue is empty");
T returnObj = this.head.data; //saving the data of the first element(head)
//If there are at least 2 nodes, else.
if(head != tail){
this.head = head.getNext();
size--;
}
else{
this.head = null;
this.tail = head;
this.size = 0;
}
return returnObj;
}
#Override
public T first() {
return this.head.data;
}
#Override
public T last() {
return this.tail.data;
}
/* I absolutely can not get past this NullPointerException that is given every time
* I try to use the iterator. It seems that current.next is always null(doesn't point to head properly?).
* HOWEVER, if you change "curr" for "head", it works. */
#Override
public Iterator<T> iterator() {
return new GenericIterator();
}
private class GenericIterator implements Iterator<T>{
public myNode<T> curr = head;
public boolean hasNext() {
return (head != null && head.next != null);
}
public T next() {
T tmp = head.data; //saving current in a temporary node because we are changing the value of current in the next line
if(hasNext()){
head = head.next;
}
return tmp;
}
}
private class myNode<T> { //parameter type T hiding type T
public T data; //The generic data the nodes contain
public myNode<T> next; //Next node
//Node constructor
public myNode(T nData) {
this.data = nData;
this.next = null;
}
public myNode<T> getNext(){
return this.next;
}
}
}
Here is the part that is giving me trouble:
/* I absolutely can not get past this NullPointerException that is given every time
* I try to use the iterator. It seems that current.next is always null(doesn't point to head properly?).
* HOWEVER, if you change "curr" for "head", it works. */
#Override
public Iterator<T> iterator() {
return new GenericIterator();
}
private class GenericIterator implements Iterator<T>{
public myNode<T> curr = head; //doesn't work with getter either.
//public myNode<T> curr = getterHead();
public boolean hasNext() {
return (curr != null && curr.next != null);
}
public T next() {
T tmp = curr.data; //NPE HERE!
if(hasNext()){
curr = curr.next;
}
return tmp;
}
}
What I have tried is getters/setters and triple-checking every other method(they work). What seems to be the problem is that when I assign curr = head, it seems that the properties from myNode do not come with.
While head.next works fine, curr.next == null, even curr.data == null while head.data works.
I've tried with public properties and printing LinkedQueue.head.next etc, it works fine.
Stacktrace:
Exception in thread "main" java.lang.NullPointerException
at dk222gw_lab4.Queue.LinkedQueue$GenericIterator.next(LinkedQueue.java:101)
at dk222gw_lab4.Queue.LinkedQueueMain.main(LinkedQueueMain.java:17)
Where line 101 & 17 are:
T tmp = curr.data; //node property .data & .next are null.
System.out.println(it.next()); //LinkedQueueMain.java(not included in post), both it.next() and it.hasNext() produce this NPE.
I am trying to implement linked list in java, but nothing gets printed out. I tried debugging it and it seems that every time the Add function gets called the previous value gets over written. However when i check the logic of it, it should work.
public class MyLinkedList {
public Node head;
public Node curr;
public MyLinkedList() {
// TODO Auto-generated constructor stub
head = null;
curr = null;
}
public void Add(int data) {
Node box = new Node();
box.data = data;
box.next = null;
curr = head;
if (curr == null) {
head = box;
curr = null;
}
else {
while (curr.next != null) {
curr = curr.next;
}
curr.next = box;
}
}
public void Print() {
curr = head;
while (curr != null) {
System.out.println(curr.data);
curr = curr.next;
}
}
}
This is what the Node class has
public class Node {
public int data;
public Node next;
}
Your code is fine. Just go and delete *.class files. It may be stuck in early stages of your code.
*.class files located under output folder (name of the folder can change depending on the IDE you used but generally under build folder.) you may need to delete that folder completely.
It works already, but I'll tidy it up for you:
public class MyLinkedList {
private Node head; //never expose a field as public
//the whole constructor was unnecessary
public void add(int data) { //methods start with a lower case
add(new Node(data)); //nodes always need data, so I'm passing in constructor
}
// this method adds an existing node rather than the previous add both
// creating, finding the end and adding
private void add(Node node) {
if (head == null) {
head = node;
} else {
lastNode().next = node;
}
}
private Node lastNode() { //finds the last node in the chain
Node curr = head; //curr is local
while (curr.next != null) {
curr = curr.next;
}
return curr;
}
public void print() { //methods start with a lower case
Node curr = head; //curr is local
while (curr != null) {
System.out.println(curr.data);
curr = curr.next;
}
}
private static class Node { //this class is just useful internally to MyLinkedList
private final int data; //final - node data doesn't change
private Node next;
private Node(int data) {
this.data = data;
}
}
}
I think I set up my class correct to be generic but when i try to call methods i cant seem to set up my other methods correct. Im I supposed to cast my variables to be generic? or do I cast my methods to variables?
public class LinkedList<E>
{
// reference to the head node.
private E head;
private int listCount;
public boolean delete(E string)
// post: removes the element at the specified position in this list.
{
Node current = head.getNext();
while(true){
if(current == null){
return false;
}else if(current.getNext().getData().equals(string)){
if(current.getNext() == null){
current.setNext(null);
}else{
current.setNext(current.getNext().getNext());
}
listCount--; // decrement the number of elements variable
return true;
}else{
current = current.getNext();
}
}
}
private class Node<E extends Comparable<E>>
{
// reference to the next node in the chain,
E next;
// data carried by this node.
// could be of any type you need.
E data;
// Node constructor
public Node(E _data)
{
next = null;
data = _data;
}
// another Node constructor if we want to
// specify the node to point to.
public Node(E _data, E _next)
{
next = _next;
data = _data;
}
// these methods should be self-explanatory
public E getData()
{
return data;
}
public void setData(E _data)
{
data = _data;
}
public E getNext()
{
return next;
}
public void setNext(E _next)
{
next = _next;
}
}
}
The types of your variables were a bit messed up.
Node.next needs to be a Node
LinkedList.head needs to be Node
Node does not need to be generic. (The E type parameter is in scope for the inner class.)
Here's a version that compiles:
class LinkedList<E> {
// reference to the head node.
private Node head;
private int listCount;
public boolean delete(E string)
// post: removes the element at the specified position in this list.
{
Node current = head;
while (true) {
if (current == null) {
return false;
} else if (current.getData().equals(string)) {
if (current.getNext() == null) {
current.setNext(null);
} else {
current.setNext(current.getNext().getNext());
}
listCount--; // decrement the number of elements variable
return true;
} else {
current = current.getNext();
}
}
}
private class Node {
// reference to the next node in the chain,
Node next;
// data carried by this node.
// could be of any type you need.
E data;
// Node constructor
public Node(E _data) {
next = null;
data = _data;
}
// another Node constructor if we want to
// specify the node to point to.
public Node(E _data, Node _next) {
next = _next;
data = _data;
}
// these methods should be self-explanatory
public E getData() {
return data;
}
public void setData(E _data) {
data = _data;
}
public Node getNext() {
return next;
}
public void setNext(Node _next) {
next = _next;
}
}
}
Looking at your delete method, I think it's a bit buggy though. When you arrive at a node where the data equals string, you change the next-pointer of that node while you should be changing the next-pointer of the previous node.
I would try something like this:
Node current = head, prev = null;
while (current != null) {
if (current.getData().equals(string)) {
// Remove current from list
if (current == head) {
head = current.getNext();
} else {
prev.setNext(current.getNext());
}
listCount--; // decrement the number of elements variable
return true;
}
prev = current;
current = current.getNext();
}