Delete node with biggest values from linked list - java

I want to delete the Node with the biggest generic T object from my linear linked list (list only has head) and return the object of this Node. Method signature must look like this and the code I got so far:
The List looks like this:
public List<T extends Comparable<T>>{
private Node<T> head;
public List(){
this.head = null;
}
//inner class Node
public class Node<T>{
T obj;
Node<T> next;
}
public Node(T obj){
this.obj = obj;
}
//the method my question is about
public T remove(){
if(head == null) return null;
else {
Node<T> act = head;
Node<T> prev = head //previous Node
Node<T> biggest;
while(act != null){
if(act.obj.compareTo(prev.obj) > 0) {
biggest = act;
}
prev = p;
p = p.next;
}
return biggest.obj;
}
}
This code only gets the biggest object but does not delete the Node. I don't know how to adapt the while loop to delete the node. If I found the biggest Element the prev.next pointer must go to the act.next Node somehow.

What your code currently does is it compares two adjacent nodes if(act.obj.compareTo(prev.obj), where I assume nodes are not ordered by value (you did not mention it in your question), so this is incorrect.
What you want to do is:
Find the biggest value in the list
Remove node with that value
T biggestValue = head.obj;
// 1
while(act != null) {
if(act.obj.compareTo(biggestValue.obj) > 0) {
biggestValue = act.obj;
}
}
// 2
while(act != null) { // that loop and its body could be simplified by using: while(!act.obj.equals(biggestValue)) but I leave it that way for brevity
if(act.obj.equals(biggestValue)) {
prev.next = act.next;
break;
}
prev = act;
act = act.next;
}

Hint: If the singly linked list contains more than one item, and you want to cut out the node that contains the largest value, you have to use two while loops, the first loop to identify what is the largest value, the second loop to find the node that contains that largest value and cut it from the list.

Related

How to insert a sorted node into a generic Linked list using java

I have encountered a problem while comparing the generic type data in which the compare to method isn't declared for comparing for example I used this to find the current and previous nodes in which the new node will be inserted between before or after them
for(prev =null,current = head; current !=null&& newNode.getData().compareTo(current.getData)<0;prev =current,current =current.getNext());
And I tried implementing comparable inside the Node class but I couldn't figure out a way to make it work since it doesn't define the greater than and less than operations.
`public class LinkedLists1<T> {
Node<T> head;
public LinkedLists1() {
this.head = null;
}
public LinkedLists1(T data) {
Node<T> temp = new Node<T>(data);
head = temp;
}
public void insert(T data) {
Node<T> newNode = new Node<T>(data);
if (head == null) {
head = newNode;
} else {
Node<T> prev = null;
Node<T> current = new Node<T>(head.getData());
implement this for loop
for (prev = null, current = head; current != null
&& newNode.compareTo(current) < 0; prev = current, current = current.getNext());
if (current != null) {
if (head == current) {
newNode.setNext(head);
head = newNode;
} else if (current.getNext() == null) {
current.setNext(newNode);
} else {
newNode.setNext(current.getNext());
current.setNext(newNode);
}
}
}
}
}`
So I tried using the compare to method but as I said it's not defined or that's what I got.
Your Node class needs to properly implement the Comparable interface. Your compareTo() method inside of the Node class should then look something like this:
public int compareTo(Node other) {
return this.data - other.data;
}
Or otherwise be defined such that if this.data comes before other.data in the intended ordering then the function returns a negative value.
Edit: compareTo() is from the Comparable interface, not the Comparator interface which uses compare()

Can an object like node update itself without any need of giving it an updated value?

(In the insert method): In the else statement, I don't understand how "front.next" is getting updated with the line: "prev.next = newNode". Theoretically, I understand it, but practically, although "prev" gets its value from "curr", which got its value from "front" itself, there is no way that front is getting updated because "prev". How are they talking to each other?
(Insert method)I have tried debugging and when it reaches the else statement that executes => prev.next = newNode; front.next gets updated as well which I just don't understand since front is nowhere being initialised again. Front is an object of itself.
public class SinglyLinkedList<T>
{
// inner class being created:
protected class Node<T extends Comparable<T>>
{
T val;
Node<T> next;
Node(T val)
{
this.val = val;
this.next = null;
}
Node(T val, Node n)
{
this.val = val;
this.next = n;
}
}
private Node front, tail;
public SinglyLinkedList()
{
this.front = this.tail = null;
}
// print method:
public void print()
{
// print the contents of the list
Node curr = front;
while (curr != null)
{
System.out.println(curr.val + " ");
curr = curr.next;
}
}
// insert method:
public void insert(T val)
{
Node newNode = new Node((Comparable) val);
// make a new node
if (front == null)
{
// empty list
front = tail = newNode;
}
else
{
// list is not empty
Node curr = front, prev = null;
// look for insert point.
while (curr != null && curr.val.compareTo(val) < 0)
{
prev = curr;
curr = curr.next;
}
// insert node before curr
newNode.next = curr;
if (curr == front)
{
// update front
front = newNode;
}
else
{
// update node before
prev.next = newNode;
}
if (tail.next != null)
{
// move tail to last node
tail = tail.next;
}
}
}
}
I expected curr to keep continuing to fill in the chain of nodes using curr.next and using "prev" as a temporary node used in the process of adding a node in between two nodes.
I also didn't expect print method to work since it begins with front node. Theoretically, it does make sense to start with front node, but looking at my code how "front" is not equalling to any value, but rather "curr" equalling "front", makes me feel that "front" shouldn't be having the access to the rest chain of nodes.
I expected "front.next" to be null, but it isn't.
Well, according to your code, the front works as the first node of the linked list, it actually equals to a certain value (a real node) because your code set it to be so a
if (front == null)
{
// empty list
front = tail = newNode;
}
and
if (curr == front)
{
// update front
front = newNode;
}
See! You indeed pointed it to a certain node with a given value.
For the update question. I think possibly you are always inserting a new node right next to the front node. Under that circumstance, the prev points to the same node as the front do. So if you update prev, you are updating front, too!

Singly Linked List implementation in Java Iterator

I'm writing a simple implementation of a Bag in Java. I am implementing Iterable and writing my own LinkedList Iterator. So I'm racking my brain; I am trying to add elements to the linked list. I have a working implementation (the commented out code in the add() function). However, I do not understand why the following code does not work:
current.item = item;
Node<T> nextNode = new Node<T>();
current.next = nextNode;
current = nextNode;
So, given that the list is empty and the current head is initialized but has no item or next: I assign item to the current item, create a new node, set it to the current's next and change the current (head) to the node I just created. Adding two items to the list, I printed out the objects for posterity:
current: Bag$Node#4524411f next: Bag$Node#401e7803
current: Bag$Node#401e7803 next: Bag$Node#10dba097
current: Bag$Node#10dba097 next: Bag$Node#1786f9d5
current: Bag$Node#1786f9d5 next: Bag$Node#704d6e83
It looks clearly, to me at least, that the next is getting set with a new node each time just fine. I get all four elements added to the bag, but the item is lost and returns null for each index. The toArray() function shows [null, null, null, null]
I'm sure it's something blindingly simple. Below is the entire implementation.
import java.util.Iterator;
public class Bag<T> implements Iterable<T> {
private Node current;
//Node<T> head;
private int numberofProducts;
T[] myBag;
int defaultCapacity;
public Iterator<T> iterator() {
return new ListIterator<T>(current);
}
public Bag(int defaultCapacity) {
this.current = new Node<T>();
this.numberofProducts = 0;
this.defaultCapacity = defaultCapacity;
}
public void add(T item) {
if(isFull()) {
System.out.println("bags full, yo");
return;
}
current.item = item;
Node<T> nextNode = new Node<T>();
current.next = nextNode;
current = nextNode;
numberofProducts++;
//Node<T> nextNode = current;
//current = new Node<T>();
//current.item = item;
//current.next = nextNode;
//numberofProducts++;
}
public Object[] toArray() {
Object[] array = new Object[size()];
int i = 0;
Node<T> node = current;
//Node<T> node = head;
while(node.next != null) {
array[i] = node.item;
node = node.next;
i++;
}
return array;
}
public boolean isEmpty() {
return this.numberofProducts <= 0;
}
public boolean isFull() {
return this.numberofProducts >= defaultCapacity;
}
public int size() {
return this.numberofProducts;
}
private class Node<T> {
private T item;
private Node<T> next;
}
private class ListIterator<T> implements Iterator<T> {
private Node<T> current;
public ListIterator(Node<T> first) {
current = first;
}
public boolean hasNext() {
return current != null;
}
public T next() {
if(hasNext()) {
T item = current.item;
current = current.next;
return item;
}
return null;
}
public void remove() {
}
}
}
The item values aren't lost. The problem is that you lose track of the head of the linked list. Your current variable keeps track of the tail already, and since your toArray() method starts at current, the while loop never executes because there are no elements after the tail element of the list.
Consequently, you just end up with an array of default-initialized Object values, i.e. null.
To fix this, you need another instance variable to keep track of the head of the list, and this is what you'll use in your toArray() method.
From what I can see, the reason it's not acting as a Linked List is because you are not retaining a reference to the first element added. Rather you retain a reference to the last (current) element added.
You can resolve this by adding a class field reference the first element added
T head
Then in your add() method, set head to the Node you create. Then when you construct your ListIterator, pass head as the parameter.
You can change add(T item) to showing like this:
public void add(T item) {
if (!isFull()) {
Node<T> toAdd = new Node<>();
toAdd.item = item;
current.next = toAdd;
current = toAdd;
if (head == null) {
head = toAdd;
}
}
}
Then add the class field Node<T> head to your Bag<T> class.
Additionally, I'm not sure why Node is a static class, plus a number of other changes I won't get into now, but I guess the class is incomplete at present.
The problem is with your logic written in the add() method. Whenever adding the new data to Bag, your root node is changing and pointing to the last node of your Bag. Since the next to last node is null, that's why the iterator is not returning anything. Refer to this link for the exact solution.

How to use compareTo() method to compare objects in a List?

I have a class called ListNode that works like a list. Using this class I want to establish a list of Magazine objects. In my MagazineList class I want to edit the add method so when I insert Magazines they will be sorted alphabetically. How can I do this?
My ListNode class:
public class ListNode {
private Object value;
private ListNode next;
//intializes node
public ListNode (Object initValue, ListNode initNext) {
value = initValue;
next = initNext;
}
//returns value of node
public Object getValue () {
return value;
}
//returns next reference of node
public ListNode getNext () {
return next;
}
//sets value of node
public void setValue (Object theNewValue) {
value = theNewValue;
}
//sets next reference of node
public void setNext (ListNode theNewNext) {
next = theNewNext;
}
}
my MagazineList class's add method:
//when instantiated, MagazineList's list variable is set to null
public void add (Magazine mag) {
ListNode node = new ListNode (mag, null);
ListNode current;
if (list == null)
list = node;
else {
current = list;
while (current.getNext() != null)
current = current.getNext();
current.setNext(node);
}
}
I used this method to compare the Magazines in the Magazine class:
//compares the names (Strings) of the Magazines.
public int compareTo(Magazine mag2) {
return (title).compareTo(mag2.toString());
}
One easy way to do this is to keep your list always sorted.
Then, each time you insert a new node, starting from the head, you should compare the the new node with each node in the list using compareTo method, and insert the new node after the node for which compareTo returns positive.
A basic implementation may be like this. You need to improve it and consider edge cases etc. though.
//when instantiated, MagazineList's list variable is set to null
public void add (Magazine mag) {
ListNode node = new ListNode (mag, null);
ListNode current;
if (list == null)
list = node;
else {
current = list; // you list head
while (node.compareTo(current) < 0)
current = current.getNext();
ListNode next = current.getNext();
current.setNext(node);
node.setNext(next);
}
}
Like this
//compares the names (Strings) of the Magazines.
public int compareTo(Magazine mag2) {
//assume that you have getTittle() method which returns Title
return title.compareTo(mag2.getTitle());
}

Inspect a Queue to print all elements

I am currently revising for my programming exam and I have came across a question from a past paper that has me rather confused.
I have two classes, Queue and Node, shown below.
The question states that I have to extend the behaviour of the Queue class by adding the necessary code to the inspectQueue method that prints to the console all the data stored within the queue.
The only solution I can think of, and it is very weak, is to have a simple ArrayList and every time an element is enqueued/dequeued then add/remove the node to/from the list.
Is there a better solution that I am glossing over? I'd really appreciate some guidance.
I've commented the code where I have implemented my "solution" the rest of the code is how it appears in the exam paper.
Thanks for your time.
Queue.java
public class Queue {
protected Node head;
protected Node last;
//added by me
private ArrayList<Node> nodes = new ArrayList<Node>();
//end my add
public boolean isEmpty() {
return (this.head == null);
}
public void enqueue(Object d) {
Node n = new Node();
n.setData(d);
nodes.add(n); //added by me
if (this.isEmpty()) {
head = n;
last = n;
}
else {
last.setNext(n);
last = n;
}
}
public Object dequeue() {
if(this.isEmpty()) {
this.last = null;
return null;
}
else {
Node h = this.head;
nodes.remove(h); //added by me
head = h.getNext();
return h.getData();
}
}
public Object peek() {
if(this.isEmpty()) {
return null;
}
else {
Node t = this.head;
return t.getData();
}
}
public void clearQueue() {
this.head = null;
this.last = null;
}
public void inspectQueue() {
//added by me (all below)
System.out.println("Inspecting Queue: (contains " + nodes.size() + " nodes)");
for(Node n : nodes) {
System.out.println(n.getData());
}
}
}
Node.java
public class Node {
protected Object data;
protected Node next;
public void setNext(Node e) {
this.next = e;
}
public Node getNext() {
return this.next;
}
public void setData(Object d) {
this.data = d;
}
public Object getData() {
return this.data;
}
}
Your nodes form a linked list, so just do
public void inspectQueue() {
Node n = head;
while (n != null) {
System.out.println(n.getData());
n = n.getNext();
}
}
This is a very basic data structure, called a LinkedList. In the your code for the Node class you can see the following:
protected Node next;
This means that every Node also holds a reference to the next Node in the list. If this Node is null, there are no more elements in the list. Knowing this, you can loop somewhat like this:
Node currentNode = this.head;
while(currentNode != null) {
System.out.println(currentNode.getData().toString());
currentNode = currentNode.getNext();
}
This eliminates the need for an ArrayList to store your references.
The LinkedList is a VERY frequently used data structure and very important to understand. If you have any questions, just go ahead and ask!
If you also want to have the size, keep a counter along, increment it each time you call getNext(), and print the size after the for loop.
You don't need the array, you have that information stored within the Node next property:
public void inspectQueue() {
Node current = head;
while(current != null) {
System.out.println(n.getData());
current = current.getNext();
}
}
That data structure is called linked list.
The simpler solution is to start with queue.head and traverse the linked list of nodes using node.next, printing the data as you go along.

Categories

Resources