Stack overflow - Merge sort on LinkedList - java

I'm trying to perform merge sort on a LinkedList(Manually implemented and not using the collections one) 🔗. Not sure why I'm getting stack overflow error ⚠. Seeking help, thank you in advance 🙂.
public class LinkedList3 {
public static class Node {
int data;
Node next;
public Node(int data) {
this.data = data;
this.next = null;
}
}
public static Node head;
public static Node tail;
public void addFirst(int data) {
Node newNode = new Node(data);
if(head == null) {
head = tail = newNode;
return;
}
newNode.next = head;
head = newNode;
}
public void addLast(int data) {
Node newNode = new Node(data);
if(head == null) {
head = tail = newNode;
return;
}
tail.next = newNode;
tail = newNode;
}
public void print() {
Node temp = head;
while(temp != null) {
System.out.print(temp.data + " -> ");
temp = temp.next;
}
System.out.println("null");
}
private Node getMid(Node head) {
Node slow = head;
Node fast = head;
while(fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
private Node merge(Node head1, Node head2) {
Node mergedLL = new Node(-1);
Node temp = mergedLL;
while(head1 != null && head2 != null) {
if(head1.data <= head2.data) {
temp.next = head1;
head1 = head1.next;
temp = temp.next;
} else {
temp.next = head2;
head2 = head2.next;
temp = temp.next;
}
}
while(head1 != null) {
temp.next = head1;
head1 = head1.next;
temp = temp.next;
}
while(head2 != null) {
temp.next = head2;
head2 = head2.next;
temp = temp.next;
}
return mergedLL.next;
}
public Node mergeSort(Node head) {
if(head == null || head.next == null) {
return head;
}
Node mid = getMid(head);
Node rightHead = mid.next;
mid.next = null;
Node newLeft = mergeSort(head);
Node newRight = mergeSort(rightHead);
return merge(newLeft, newRight);
}
public static void main(String args[]) {
LinkedList3 ll = new LinkedList3();
ll.addFirst(1);
ll.addFirst(2);
ll.addFirst(3);
ll.addFirst(4);
ll.addFirst(5);
ll.print();
ll.head = ll.mergeSort(ll.head);
ll.print();
}
}
I assume that I might be missing/error/typo something in the mergeSort method. I've checked the code multiple times but getting the same error. I couldn't find a solution or a reason for overflow in this linked list.
5 -> 4 -> 3 -> 2 -> 1 -> null
Exception in thread "main" java.lang.StackOverflowError
at LinkedList3.getMid(LinkedList3.java:54)
at LinkedList3.mergeSort(LinkedList3.java:100)
at LinkedList3.mergeSort(LinkedList3.java:105)
at LinkedList3.mergeSort(LinkedList3.java:105)
at LinkedList3.mergeSort(LinkedList3.java:105)
at LinkedList3.mergeSort(LinkedList3.java:105)
at LinkedList3.mergeSort(LinkedList3.java:105)

Related

Folding a linked list using a Stack

Here is my program to fold a linked list using a Stack:
public Node middle(Node head) {
Node slow = head;
Node fast = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
public Node foldList(Node head){
Node mid = middle(head);
Node f = mid.next;
Stack<Node> stacks = new Stack<>();
if (head == null) return head;
while (f != null){
stacks.push(f);
f = f.next;
}
Node temp = head;
Node forv = head.next;
while(!stacks.isEmpty()) {
temp.next = stacks.pop();
temp = temp.next;
temp.next = forv;
temp = temp.next;
forv = forv.next;
}
return head;
}
Here is the code of the middle() and foldList() methods. When I run it it gets stuck in an infinite loop. Can anybody help me find out why this is happening?
The problem is that you are doing this:
linked list: 1-2-3-4-5-6
Put second half in a Stack:
linked list: 1-2-3-4-5-6
stack: 5-6
Insert the stack nodes between the linked list nodes:
linked list: 1-6-2-3-4-5-6-2-3-4-5-6-2-3-4-5-6.....infinite
You need to remove the second half of the nodes (the ones put on the stack) from the linked list before you start folding.
Since it's a linked list, you can simply nullify mid.next:
public Node foldList(Node head){
Node mid = middle(head);
Node f = mid.next;
// remove the second half
mid.next = null
Stack<Node> stacks = new Stack<>();
if (head == null) return head;
while (f != null){
stacks.push(f);
f = f.next;
}
Here's my full code, using Deque instead of Stack (because Stack is old and moldy):
import java.util.ArrayDeque;
import java.util.Deque;
public class LinkedListFolder {
public static void main(String[] args) {
Node head = createLinkedList();
foldList(head);
print(head);
}
private static Node createLinkedList() {
Node head = new Node(1);
Node current = head;
for (int i = 2; i < 7; i++) {
current.next = new Node(i);
current = current.next;
}
return head;
}
private static void print(Node node) {
System.out.println(node);
while (node.next != null) {
node = node.next;
System.out.println(node);
}
}
public static void foldList(Node head) {
if (head == null) {
return;
}
Deque<Node> nodesToFold = getNodesToFold(head);
Node current = head;
Node successor = head.next;
while (!nodesToFold.isEmpty()) {
current.next = nodesToFold.pop();
current = current.next;
current.next = successor;
current = current.next;
successor = successor.next;
}
}
private static Deque<Node> getNodesToFold(Node head) {
Node middle = findMiddle(head);
Node current = middle.next;
middle.next = null;
Deque<Node> nodesToFold = new ArrayDeque<>();
while (current != null) {
nodesToFold.push(current);
current = current.next;
}
return nodesToFold;
}
public static Node findMiddle(Node head) {
Node slow = head;
Node fast = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
static class Node {
public int value;
public Node next;
public Node(int value) {
this.value = value;
}
#Override
public String toString() {
return String.format("Node{value=%d}", value);
}
}
}
Output:
Node{value=1}
Node{value=6}
Node{value=2}
Node{value=5}
Node{value=3}
Node{value=4}

Reverse singly linked list

I have the below program to reverse elements in a singly linked list. I can't get it to work. I have used simple swapping of variables technique to swap the nodes but when I print, it doesn't go beyond the first node.
public static void reverseLinkedList(Node head) {
Node current = head;
Node temp = null;
while (current != null && current.next != null) {
temp = current;
current = current.next;
current.next = temp;
}
}
public static void printData(Node head) {
Node currentNode = head;
while (true) {
System.out.println(currentNode.data);
if (currentNode.next != null) {
currentNode = currentNode.next;
} else {
break;
}
}
}
I prefer to return the head node after the function. Keeps thing simple
Node reverse(Node node)
{
Node prev = null;
Node current = node;
Node next = null;
while (current != null) {
next = current.next;
current.next = prev;
prev = current;
current = next;
}
node = prev;
return node;
}
Alternatively you can opt for the simpler recursive version
Node reverse(Node head) {
if(head == null) {
return head;
}
if(head.next == null) {
return head;
}
Node newHeadNode = reverse(head.next);
head.next.next = head;
head.next = null;
return newHeadNode;
}
You are assigning the next of the current variable to itself which is wrong. You can do like below.
public void reverseLL(Node head) {
Node currentNode = head, prevLink = null, nextNode = null;
while (currentNode != null) {
nextNode = currentNode.next;
currentNode.next = prevLink;
prevLink = currentNode;
currentNode = nextNode;
}
head = prevLink;
}
In your algorithm the first two nodes of the list creates a loop after the first iteration of the while loop.It's better to use the below algorithm.
public static void reverseLinkedList(Node head) {
Node current = head;
Node prev = head;
Node next = head.next;
while (current != null && current.next != null) {
current=next;
next=current.next;
current.next=prev;
prev=current;
}
head=current;
}

What is the right way to sort a linked list in Java?

I have this linked list:
class Node {
Node next;
int num;
public Node(int val) {
num = val;
next = null;
}
}
public class LinkedList {
Node head;
public LinkedList(int val) {
head = new Node(val);
}
public void append(int val) {
Node tmpNode = head;
while (tmpNode.next != null) {
tmpNode = tmpNode.next;
}
tmpNode.next = new Node(val);
}
public void print() {
Node tmpNode = head;
while (tmpNode != null) {
System.out.print(tmpNode.num + " -> ");
tmpNode = tmpNode.next;
}
System.out.print("null");
}
public static void main(String[] args) {
LinkedList myList = new LinkedList(8);
myList.append(7);
myList.append(16);
myList.print();
}
}
and I want to know how should I sort this linked list? I tried to sort it but strange numbers starts comming out and in other cases it do nothing and sort nothing.
you can make the linked list sorted while insert itself. So that you dont need another function to sort it. You didn't consider the initial scenario where the head will be null only that is the error
public void insert(int val) {
Node currentNode = head;
Node nextNode = head.next;
if (head==null) {
head = new Node(val);
head.next = null;
return;
}
if (currentNode.num > val) {
Node tmpNode = head;
head = new Node(val);
head.next = tmpNode;
return;
}
if (nextNode != null && nextNode.num > val) {
currentNode.next = new Node(val);
currentNode.next.next = nextNode;
return;
}
while (nextNode != null && nextNode.num < val) {
currentNode = nextNode;
nextNode = nextNode.next;
}
currentNode.next = new Node(val);
currentNode.next.next = nextNode;
}

Removing Odds from a LinkedList recursively using index

I am having a little bit of difficulties with the Recursive concept.
Given a LinkedList with Integer values
L1 = (2->1->4->6->3)
L2= (1->9->6->3)
The function should remove the Odd numbers from the linkedlist starting at the integer N and returns a reference to the new head
i.e
L1.deleteOdd(2) = > (2->4->6)
L2.deleteOdd(1) = > (6)
I implemented a normal iterative function that does the job, here it is
public node deleteOdd(int n) {
node head = this.head;
if (head == null)
return head;
while (head != null) {
if (head.data == n) {
node head2 = head;
while (head2.next != null) {
if (head2.next.data % 2 != 0) {
head2.next = head2.next.next;
} else {
head2 = head2.next;
}
}
if (head.data % 2 != 0) {
return head.next;
}
return head;
}
head = head.next;
}
return head;
}
Now I am trying to do a recursive function, I tried doing something but it seems like I am missing something.
My recursive function is
public node DeleteOddR(int n) {
node head = this.head;
if (head == null)
return head;
if (head != null) {
if (head.data == n) {
node head2 = head;
if (head2.next.data % 2 != 0)
{
head2.next = head2.next.next;
} else {
head2 = head2.next;
}
if (head.data % 2 != 0) {
return DeleteOddR(head.next.data);
} else {
head.next = DeleteOddR(head.next.data);
return head;
}
} else {
head = head.next;
}
}
return head;
}
The results is
node f = l1.DeleteOddR(2);
display(f); // Gives- >2->3->4->6
I would appreciate helps..
I write one may meet your requirement .
Save the previous node and recurse using it .
public class LinkedList{
public static void main(String[] args) {
LinkedList node0 = new LinkedList(0);
LinkedList node1 = new LinkedList(1);
LinkedList node2 = new LinkedList(2);
LinkedList node3 = new LinkedList(3);
LinkedList node4 = new LinkedList(4);
LinkedList node5 = new LinkedList(5);
LinkedList node6 = new LinkedList(6);
LinkedList node7 = new LinkedList(7);
LinkedList node8 = new LinkedList(8);
node0.setNext(node1);
node1.setNext(node2);
node2.setNext(node3);
node3.setNext(node4);
node4.setNext(node5);
node5.setNext(node6);
node6.setNext(node7);
node7.setNext(node8);
node0.removeOddFromVale(3, false);
System.out.println();
}
public void removeOddFromVale(int value,boolean start){
LinkedList head = this;
LinkedList prev = this;
if(!start){
while(head != null){
if(head.value == value){
start = true;
break;
}
prev = head;
head = head.next;
}
}
if(prev != null && head != null){
if(prev == head){
head = head.next;
}
if (head != null) {
if (head.value % 2 == 0) {
prev.next = head.next;
} else {
prev = prev.next;
head = head.next;
}
if (prev != null) {
prev.removeOddFromVale(value, true);
}
}
}
}
private LinkedList next;
private int value;
public LinkedList(int value){
this.value = value;
}
public LinkedList getNext() {
return next;
}
public void setNext(LinkedList next) {
this.next = next;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}

Singly linked list removing element using head and tail reference

I have to implement a singly linked list for my project and I'm having trouble getting the remove method to work. I have searched on here for answers but I can't find any that incorporate the tail reference. My project needs to have a head and tail reference in the list and needs to be updated wherever necessary. This is my class and the remove method:
public class BasicLinkedList<T> implements Iterable<T> {
public int size;
protected class Node {
protected T data;
protected Node next;
protected Node(T data) {
this.data = data;
next = null;
}
}
protected Node head;
protected Node tail;
public BasicLinkedList() {
head = tail = null;
}
public BasicLinkedList<T> addToEnd(T data) {
Node n = new Node(data);
Node curr = head;
//Check to see if the list is empty
if (head == null) {
head = n;
tail = head;
} else {
while (curr.next != null) {
curr = curr.next;
}
curr.next = n;
tail = n;
}
size++;
return this;
}
public BasicLinkedList<T> addToFront(T data) {
Node n = new Node(data);
if(head == null){
head = n;
tail = n;
}
n.next = head;
head = n;
size++;
return this;
}
public T getFirst() {
if (head == null) {
return null;
}
return head.data;
}
public T getLast() {
if(tail == null){
return null;
}
return tail.data;
}
public int getSize() {
return size;
}
public T retrieveFirstElement() {
// Check to see if the list is empty
if (head == null) {
return null;
}
Node firstElement = head;
Node curr = head.next;
head = curr;
size--;
return firstElement.data;
}
public T retrieveLastElement() {
Node curr = head;
Node prev = head;
// Check to see if the list is empty
if (head == null) {
return null;
} else {
// If there's only one element in the list
if (head.next == null) {
curr = head;
head = null;
} else {
while (curr.next != null) {
prev = curr;
curr = curr.next;
}
tail = prev;
tail.next = null;
}
}
size--;
return curr.data;
}
public void remove(T targetData, Comparator<T> comparator) {
Node prev = null, curr = head;
while (curr != null) {
if (comparator.compare(curr.data, targetData) == 0) {
//Check to see if we need to remove the very first element
if (curr == head) {
head = head.next;
curr = head;
}
//Check to see if we need to remove the last element, in which case update the tail
else if(curr == tail){
curr = null;
tail = prev;
prev.next = null;
}
//If anywhere else in the list
else {
prev.next = curr.next;
curr = curr.next;
}
size--;
} else {
prev = curr;
curr = curr.next;
}
}
}
public Iterator<T> iterator() {
return new Iterator<T>() {
Node current = head;
#Override
public boolean hasNext() {
return current != null;
}
#Override
public T next() {
if(hasNext()){
T data = current.data;
current = current.next;
return data;
}
return null;
}
#Override
public void remove(){
throw new UnsupportedOperationException("Remove not implemented.");
}
};
}
}
I have went through many iterations of this method and each time I either lose the head reference, the tail reference or I don't remove the element and I am stumped trying to figure it out. For reference here is the test I'm running on it. I don't even fail the test, it just says failure trace.
public void testRemove(){
BasicLinkedList<String> basicList = new BasicLinkedList<String>();
basicList.addToEnd("Blue");
basicList.addToEnd("Red");
basicList.addToEnd("Magenta");
//Blue -> Red -> Magenta -> null
basicList.remove("Red", String.CASE_INSENSITIVE_ORDER);
//Blue -> Magenta -> null
assertTrue(basicList.getFirst().equals("Blue"));
//getLast() returns the tail node
assertTrue(basicList.getLast().equals("Magenta"));
}
EDIT: Forgot to mention that the remove method should be removing all instances of the target data from the list.
I see only 1 bug. If your list is initially empty the following method will cause a loop where you have one node whose next refers to itself:
public BasicLinkedList<T> addToFront(T data) {
Node n = new Node(data);
// The list was empty so this if is true
if(head == null){
head = n;
tail = n;
}
n.next = head;
// now head == n and n.next == head == n so you've got a circle
head = n;
size++;
return this;
}
You can fix this like so:
public BasicLinkedList<T> addToFront(T data) {
Node n = new Node(data);
if(head == null){
tail = n;
}
n.next = head;
head = n;
size++;
return this;
}

Categories

Resources