How could I re-write this java method with a while loop? - java

It's supposed to take the last element out of a pseudo-LinkedList. The instructions suggested using a while loop to find the next-to-last element.
public String removeFromEnd() {
String removed = null;
if (head == null) {
return removed;
} else if (head.getNext() == null) {
removed = head.getName();
head = null;
} else if (head.getNext().getNext() == null) {
removed = head.getNext().getName();
head.setNext(null);
}
return removed;
}
Past attempts usually look similar to this:
public String removeFromEnd() {
String removed = null;
while (head.getNext().getNext() == null){
removed = head.getNext().getName();
head.setNext(null);
}
if (head.getNext() == null){
removed = head.getName();
head = null;
}
return removed;
}

Node node = head;
Node prev = null;
while (node != null && node.getNext() != null) {
prev = node;
node = node.getNext();
}

In your attempt code...
while (head.getNext().getNext() == null){
removed = head.getNext().getName();
head.setNext(null);
}
You'll only enter this loop when head is already the second-to-last element. You want to loop until head is the second-to-last element. Does that help at all?

// Java Code
public String removeFromEnd() {
String removed = null;
Node prev = null;
Node node = head;
while(node != null && node.getNext() != null)
{
prev = node;
node = node.getNext();
}
//the while loop should move the node to the end of the list
if(node != null)
{
removed = node.getName();
node = prev;
node.getNext().removeNode();
node.setNext(null);
}
return removed;
}

Related

How to delete the first node of doubly linked list

I have an implementation of doubly linked list , and I'm trying to delete a particular node at a given position. I managed to delete the second node to the last node but when I try to delete the first node it fails, I wonder what's wrong with my code.
I've already tried this but still doesn't work
head.next.previous = null;
head = head.next;
This is my code
public class Proses {
private class Node{
String Matkul;
int NilaiUts;
int NilaiUAS;
Node previous;
Node next;
public Node(String Matkul, int Nilai, int NilaiUAS) {
this.Matkul = Matkul;
this.NilaiUts = Nilai;
this.NilaiUAS = NilaiUAS;
}
}
Node head, tail = null;
public void addNode(String matkul, int Nilai, int NilaiUAS) {
Node newNode = new Node(matkul, Nilai, NilaiUAS);
if(head == null) {
head = tail = newNode;
head.previous = null;
tail.next = null;
} else {
tail.next = newNode;
newNode.previous = tail;
tail = newNode;
tail.next = null;
}
}
public void delete(int position){
if (head == null || n <= 0)
return;
Node current = head;
int i;
for (i = 1; current != null && i < position; i++)
{
current = current.next;
}
if (current == null)
return;
deleteNode(head, current);
}
//delete function
public Node deleteNode(Node head, Node del){
if (head == null || del == null){
return null;
}
if (head == del){
head = del.next;
del.next.previous = null;
}
if (del.next != null){
del.next.previous = del.previous;
}
if (del.previous != null){
del.previous.next = del.next;
}
del = null;
return head;
}
}
Using your code, if the scenario is such that it ends up with 1 node (head will be pointing to this node) and you want to delete this node (i.e. head), code will fail with NullPointerException at
del.next.previous = null;
as del.next is NULL;
Use can take a look at below code to delete a Node from doubly linked list
// Function to delete a node in a Doubly Linked List.
// head_ref --> pointer to head node pointer.
// del --> data of node to be deleted.
void deleteNode(Node head_ref, Node del)
{
// Base case
if (head == null || del == null) {
return;
}
// If node to be deleted is head node
if (head == del) {
head = del.next;
}
// Change next only if node to be deleted
// is NOT the last node
if (del.next != null) {
del.next.prev = del.prev;
}
// Change prev only if node to be deleted
// is NOT the first node
if (del.prev != null) {
del.prev.next = del.next;
}
// Finally, free the memory occupied by del
return;
}
code ref: https://www.geeksforgeeks.org/delete-a-node-in-a-doubly-linked-list/
The problem with your code is that, head is not getting changed in deleteNode function because it's pass by value. Consider the following scenario:
You are deleting the position 1. Head is pointing to the node1, so
it store the address of node1. assume it's 1001.
Now you call deleteNode function with head reference and currentNode, so head reference is get passed to the function argument as pass by value. so in function argument head contains the address 1001.
Now you perform the delete operation, so the function's head is changing it's position to the next node. But, your class member's head is still pointing to the first position.
To overcome this, you can set the head again, because you are returning it from the deleteNode function. Like:
Change the code as follow
public void delete(int position){
if (head == null || n <= 0)
return;
Node current = head;
int i;
for (i = 1; current != null && i < position; i++)
{
current = current.next;
}
if (current == null)
return;
head = deleteNode(head, current);
}

Delete specific element from LinkedList....?

I am trying to delete an specific element from the linkedlist, however i am getting null pointer exception. Could any one pls fix my below mentioned code...
public void deleteElement(T num)
{
Node<T> ele = new Node<T>(num);
if(head == null){
System.out.println("Underflow");
return;
}
Node<T> temp = head;
while(temp != null)
{
if(temp.data == num){
temp.previous.next = temp.next;
return;
}
else
temp = temp.next;
}
size--;
}
You should modify inside your while loop like this:
while(temp != null)
{
if(temp.data == num) {
if(temp.previous != null) {
temp.previous.next = temp.next;
}
// you have to link-up the next's previous with temp's previous too
if(temp.next != null) {
temp.next.previous = temp.previous;
}
temp = null; // to deference the node and let garbage collector to delete/clear this node
break; // don't return here otherwise size-- won't execute
}
temp = temp.next;
}
Before referencing temp.next and temp.previous as lvalue you should check whether they are null otherwise it will throw NullPointerException.
Hope it helps!
You have to find Node object whose data is equal to T num. Use such loop:
for (Node<T> x = first; x != null; x = x.next) {
if (num.equals(x.data)) {
unlink(x);
return true;
}
}
Where first is pointer to first node. In method remove you have to unlink found Node x from linked list:
T remove(Node<T> x) {
// assert x != null;
final T element = x.data;
final Node<T> next = x.next;
final Node<T> prev = x.prev;
if (prev == null) {
//if x is first node(head)
first = next;
} else {
// link x.next to x.prev.next
prev.next = next;
//unlink x
x.prev = null;
}
if (next == null) {
//if x is last node(tail)
last = prev;
} else {
// link x.prev to x.next.prev
next.prev = prev;
//unlink x
x.next = null;
}
// reset data
x.data = null;
size--;
return element;
}

Delete last element in singleLinked List

I am making a simple linked list and I'm trying to implement a method that allows me to delete the last node of the linked list. At some point, my method is wrong and I'm not sure where the error is and how to fix it. Here is the code!
public Nodo deleteEnd() {
Nodo aux;
if (head == null) {
throw new NoSuchElementException("Element cant be deleted");
} else {
aux = head;
while (aux.next.next != null) {
aux = aux.next;
}
size--;
}
return aux;
}
You need to assign the next of the last but not least node to null:
if(head.next == null) {
// head is last!
head = null;
size = 0;
} else {
previous = head;
current = head.next;
// while current is not last, keep going
while(current.next != null) {
previous = current;
current = current.next;
}
// current is now on last!
previous.next = null;
size--;
}
public Nodo deleteEnd() {
if (head == null) {
throw new NoSuchElementException("Element can't be deleted");
}
Nodo current = head;
Nodo next = current.next;
// Check if there is only the head element.
if ( next == null )
{
size--;
head = null;
return current;
}
// Skip to the end.
while (next.next != null) {
current = next;
next = next.next;
}
// Break the link to the next element.
current.next = null;
size--;
return next;
}
Add
aux.next = null;
after the while loop - then there will be no reference to the last element.
try reducing one .next:
while (aux.next != null) {
aux = aux.next;
}

Recursive MergeSort on a Linked List using Java

I searched on the net for a good clean and simple implentation of a merge sort algorithm in Java for a Linked List that uses recursion.
I couldn't find a nice one so Im trying to implement it here. but Im stuck.
Here is what I have so far:
public List mergeSortList(Node head, Node tail) {
if ((head == null) || (head.next == null))
return;
Node middle = this.findMiddle(head);
List left = mergeSortList(this.head, middle);
List right = mergeSortList(middle.next, tail);
return merge(left, right);
}
private List merge(List left, List right) {
List returnedList = new LinkedList();
}
private Node findMiddle(Node n) {
Node slow, fast;
slow = fast = n;
while (fast != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
Can someone help me correct any errors and fill the stubs please.
Thanks
First error is in following :-
while(fast != null && fast.next.next != null)
{
slow = slow.next;
fast = fast.next.next;
}
fast.next can be null when you do fast.next.next , considering the case when no of elements is odd.
Here is a modified code:-
while(fast != null && fast.next.next != null)
{
slow = slow.next;
if(fast.next!=null)
fast = fast.next.next;
else break;
}
Here is another modification:-
public List mergeSortList(Node head)
{
if ( (head == null) || (head.next == null))
return head;
Node middle = this.findMiddle(head);
Node first = head;
Node second = middle.next;
middle.next = null;
Node left = mergeSortList(first);
Node right = mergeSortList(second);
return merge(left, right);
}
Explanation: You donot need to pass tail to the function, You can split the list at middle into two separate list ending with null. And after recursion of two list just reconnect them to prevent loss of original list
Here is clean and simple implementation for Merge Sort on LinkedList
public class MergeSortLinkedList {
static class Node {
Node next;
int value;
Node(int value) {
this.value = value;
}
}
public static void main(String[] args) {
Node head = new Node(10);
head.next = new Node(5);
head.next.next = new Node(2);
head.next.next.next = new Node(1);
head.next.next.next.next = new Node(6);
head.next.next.next.next.next = new Node(8);
head.next.next.next.next.next.next = new Node(3);
head.next.next.next.next.next.next.next = new Node(2);
print(head);
Node sortedHead = mergeSort(head);
print(sortedHead);
}
static void print(Node head) {
Node tmp = head;
while (tmp != null) {
System.out.print(tmp.value + "->");
tmp = tmp.next;
}
System.out.println();
}
static Node getMiddle(Node head) {
if (head == null || head.next == null) {
return head;
}
Node slow = head;
Node fast = head;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
static Node sortedMerge(Node left, Node right) {
if (left == null) {
return right;
}
if (right == null) {
return left;
}
if (left.value < right.value) {
left.next = sortedMerge(left.next, right);
return left;
} else {
right.next = sortedMerge(left, right.next);
return right;
}
}
static Node mergeSort(Node head) {
if (head == null || head.next == null) {
return head;
}
Node middle = getMiddle(head);
Node middleNext = middle.next;
middle.next = null;
Node left = mergeSort(head);
Node right = mergeSort(middleNext);
return sortedMerge(left, right);
}
}
This looks like a good start. Your merge method is going to work just like any other merge sort implementation except you're dealing with lists instead of integers.
What you need to do is:
create a new list to return ('result')
compare the first element in List 'left' to the first in List 'right'
copy the smaller element to the result
advance your pointer into whichever list the smaller element came from
repeat until you hit the end of a list
copy all the remaining elements to the result
Take a stab at that (post your updated code) and we'll be happy to help you out more from there.
Solution divided in two methods,
First method is recursive method what we call from main(), then divide list using fast and slow pointer technique (fast walks 2 step when slow walks one), now call itself recursively with both the lists, and combine returned list using second method mergeSortedList, also we are calling mergeSortedList again and again within the recursion, so at the very end when there is only one element left in each list, we compare them and add together in right order.
ListNode sortList(ListNode head) {
if (head == null || head.next == null) return head;
ListNode fast = head;
ListNode slow = head;
// get in middle of the list :
while (fast.next!= null && fast.next.next !=null){slow = slow.next; fast = fast.next.next;}
fast = slow.next;
slow.next=null;
return mergeSortedList(sortList(head),sortList(fast));
}
ListNode mergeSortedList(ListNode firstList,ListNode secondList){
ListNode returnNode = new ListNode(0);
ListNode trackingPointer = returnNode;
while(firstList!=null && secondList!=null){
if(firstList.val < secondList.val){trackingPointer.next = firstList; firstList=firstList.next;}
else {trackingPointer.next = secondList; secondList=secondList.next;}
trackingPointer = trackingPointer.next;
}
if (firstList!=null) trackingPointer.next = firstList;
else if (secondList!=null) trackingPointer.next = secondList;
return returnNode.next;
}
}
Working solution in java. Go to the link below:
http://ideone.com/4WVYHc
import java.util.*;
import java.lang.*;
import java.io.*;
class Node
{
int data;
Node next;
Node(int data){
this.data = data;
next = null;
}
void append(Node head, int val){
Node temp = new Node(val);
Node cur = head;
if(head == null)
{
return;
}
while(cur.next != null)
{
cur = cur.next;
}
cur.next = temp;
return;
}
void display(){
Node cur = this;
while(cur != null)
{
System.out.print(cur.data + "->");
cur = cur.next;
}
}
}
class Ideone
{
public Node findMiddle(Node head){
if(head == null )
return null;
Node slow, fast;
slow = head;
fast = head;
while(fast != null && fast.next != null && fast.next.next != null){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
public Node merge(Node first, Node second){
Node head = null;
while(first != null && second != null){
if(first.data < second.data){
if(head == null){
head = new Node(first.data);
}
else
head.append(head,first.data);
first = first.next;
}
else if(second.data < first.data){
if(head == null){
head = new Node(second.data);
}
else
head.append(head,second.data);
second = second.next;
}
else{
if(head == null){
head = new Node(first.data);
head.append(head,second.data);
}
else{
head.append(head,first.data);
head.append(head,second.data);
}
second = second.next;
first = first.next;
}
}
while(first != null){
if(head == null){
head = new Node(first.data);
}
else
head.append(head,first.data);
first = first.next;
}
while(first != null){
if(head == null){
head = new Node(first.data);
}
else
head.append(head,first.data);
first = first.next;
}
while(second != null){
if(head == null){
head = new Node(second.data);
}
else
head.append(head,second.data);
second = second.next;
}
return head;
}
public Node mergeSort(Node head){
if(head == null)
return null;
if(head.next == null)
return head;
Node first = head;
Node mid = findMiddle(first);
Node second = mid.next;
mid.next = null;
Node left = mergeSort(first);
Node right = mergeSort(second);
Node result = merge(left, right);
return result;
}
public static void main (String[] args) throws java.lang.Exception
{
Node head = new Node(5);
head.append(head,1);
head.append(head,5);
head.append(head,1);
head.append(head,5);
head.append(head,3);
System.out.println("Unsoreted linked list:");
head.display();
Ideone tmp = new Ideone();
Node result = tmp.mergeSort(head);
System.out.println("\nSorted linked list:");
result.display();
}
}
Below is the Java version of the post to sort numbers in linked list using merge sort.
import java.util.ArrayList;
public class SortNumbersInLinkedListUsingMergeSort {
Node head;
public static void main(String[] args) {
SortNumbersInLinkedListUsingMergeSort sll = new SortNumbersInLinkedListUsingMergeSort();
// creating an unsorted linked list
sll.head = new Node(2);
sll.head.next = new Node(5);
sll.head.next.next = new Node(3);
sll.head.next.next.next = new Node(-1);
sll.head.next.next.next.next = new Node(1);
printList(sll.head);
sll.head = Merge(sll.head);
printList(sll.head);
}
//
public static Node Merge(Node head){
// if linked list has no or only one element then return
if (head == null || head.next == null){
return null;
}
// split the linked list into two halves, (front and back as two heads)
ArrayList<Node> list = splitIntoSublists(head);
// Recursively sort the sub linked lists
Merge(list.get(0));
Merge(list.get(1));
// merge two sorted sub lists
head = mergeTwoSortedLists(list.get(0), list.get(1));
return head;
}
// method to merge two sorted linked lists
public static Node mergeTwoSortedLists(Node front, Node back){
Node result;
if (front == null){
return back;
}
if (back == null){
return front;
}
if (front.data >= back.data){
result = back;
result.next = mergeTwoSortedLists(front, back.next);
}
else{
result = front;
result.next = mergeTwoSortedLists(front.next, back);
}
return result;
}
// method to split linked list into two list in middle.
public static ArrayList<Node> splitIntoSublists(Node head){
Node slowPointer;
Node fastPointer ;
Node front = null;
Node back = null;
ArrayList<Node> li = new ArrayList<Node>();
if (head == null || head.next == null){
front = head;
back = null;
}
else{
slowPointer= head;
fastPointer = head.next;
while (fastPointer != null && fastPointer.next != null){
slowPointer = slowPointer.next;
fastPointer = fastPointer.next.next;
}
front = head;
back = slowPointer.next;
slowPointer.next = null;
}
li.add(front);
li.add(back);
return li;
}
// method to print linked list
public static void printList(Node head){
Node pointer = head;
while (pointer != null){
System.out.print(pointer.data + " ");
pointer = pointer.next;
}
System.out.println();
}
}
// class to define linked list
class Node{
int data;
Node next;
public Node (int data){
this.data = data;
}
}
Here is a working example :
public class MergeSort{
public Node head = null;
public class Node {
int val;
Node next;
public Node () {//Constructor
val = 0;
next = null;
}
public Node (int i) { //constructor
val = i;
next = null;
}
}
public void insert ( int i) { //inserts node at the beginning
Node n = new Node(i);
n.next = head;
head = n;
}
public void printList (Node head) {
while (head != null) {
System.out.println (head.val);
head = head.next;
}
}
public Node sort (Node head) {
if ( head == null || head.next ==null ) return head; // no need to sort if there's no node or only one node in the Linked List
Node mid = find_Mid (head); // find middle of the LinkedList
Node sHalf = mid.next ; mid.next = null; //Splitting into two linked lists
Node h = merge ( sort(head), sort(sHalf) ); //Call merge recursively
return h;
}
public Node merge ( Node n1 , Node n2) {
Node curr = null;
if ( n1 == null )
return n2; //n1 empty
if ( n2 == null )
return n1; // n2 empty
if ( n1.val < n2.val ) {
curr=n1;
curr.next = merge (n1.next, n2); //Call merge recursively
}
else {
curr = n2;
curr.next = merge (n1, n2.next); //Call merge recursively
}
return curr;
}
public Node find_Mid (Node head) {
Node slow = head; Node fast = head;
while ( fast.next != null && fast.next.next != null ) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
public static void main(String []args){
System.out.println("Hello World");
MergeSort m = new MergeSort ();
m.insert ( 3 );
m.insert ( 4 );
m.insert ( 16 );
m.insert ( 10 );
m.insert ( 5 );
m.insert ( 1 );
m.insert ( -5 );
m.printList(m.head);
Node n = m.find_Mid (m.head);
System.out.println("Middle is :" + n.val);
m.head = m.sort(m.head);
m.printList(m.head);
}
}

What is the correct way to return booleans from something like an insert function?

I'm playing around with implementing a linked list that has an insert function that returns true once the node has been inserted. What is the correct way to conceptually return false in this type of scenario?
public boolean insert(int d) {
if (head == null) {
head = new Node(d);
return true;
}
if (head.data > d) {
Node holder = head;
Node newNode = new Node(d);
head = newNode;
head.next = holder;
holder.prev = newNode;
return true;
}
Node tmpNode = head;
while (tmpNode.next != null && tmpNode.next.data < d) {
tmpNode = tmpNode.next;
}
Node prevTmp = tmpNode;
Node insertedNode = new Node(d);
if (tmpNode.next != null) {
Node nextTmp = tmpNode.next;
insertedNode.next = nextTmp;
nextTmp.prev = insertedNode;
}
prevTmp.next = insertedNode;
insertedNode.prev = prevTmp;
return true;
}
In your case insert() method should be void since you are returnung true in all situtations. Returning boolean means that there are situations when you cannot insert an element into the collection, eg duplicates are not allowed

Categories

Resources