Java: LinkedList Reverse - java

I am trying to implement the reverse function of my own LinkedList implementation. Using my implementation of LinkedList:
public class LinkedList<T> {
public Node head;
public LinkedList(){
// Add HEAD
head = new Node(null);
}
public void add(T data){
getLastNode().next = new Node(data);
}
public void insert(int index, T data){
if(index == 0){
throw new Error(); // TODO: What is the Error Type?
}
Node current = head;
for (int i = 0; i != index - 1 ; i ++) {
current = current.next;
if (current == null){
throw new IndexOutOfBoundsException();
}
}
Node next = current.next;
Node newNode = new Node(data);
current.next = newNode;
newNode.next = next;
}
public T get(int index){
return getNode(index).data;
}
public void delete(int index){
if (index == 0){
throw new IndexOutOfBoundsException("Cannot delete HEAD node");
}
Node prev = getNode(index - 1);
Node next = prev.next.next;
prev.next = null;
prev.next = next;
}
public void reverse(){ // TODO: Last node links to a null node
Node prev = null;
Node current = head;
Node next = null;
while(current != null){
next = current.next;
current.next = prev;
prev = current;
current = next;
}
head = new Node(null);
head.next = prev;
}
public void display(){
Node current = head;
String diagram = String.format("head->");
while(current.next != null){
current = current.next;
diagram += String.format("%s->", current.data);
}
System.out.println(diagram);
}
private Node getNode(int index){
Node node = head;
for(int i = 0; i != index; i++){
node = node.next;
if(node == null){
throw new IndexOutOfBoundsException();
}
}
return node;
}
private Node getLastNode(){
Node current = head;
while(current.next != null){
current = current.next;
}
return current;
}
public class Node {
private Node next;
private T data;
public Node(T data){
this.data = data;
}
public Node getNext(){
return this.next;
}
}
}
And this main function:
LinkedList list = new LinkedList();
list.add("e1");
list.add("e2");
list.add("e3");
list.add("e4");
list.display();
list.reverse();
list.display();
The displayed result is:
head->e1->e2->e3->e4->
head->e4->e3->e2->e1->null->
This has happened due to the fact that e1 is still connected to the head. If I use the implementation of reverse available online:
Node prev = null;
Node current = head;
Node next = null;
while(current != null){
next = current.next;
current.next = prev;
prev = current;
current = next;
}
head = prev;
Then the result will ditch e4: head->e3->e2->e1->null->
What am I doing here? Why is my implementation different than everybody else's?
Also: Why does everyone use a reverse function that has head as an argument which could be problematic if the developer enters a different node?

You are using a first node as a head of your list. The solution for the reverse function is this:
head.next = prev;
You have to preserve the 'head' node, but change its 'next' field.
The rest of the function don't change at all:
public void reverse(){ // TODO: Last node links to a null node
Node prev = null;
Node current = head.next;
Node next = null;
while(current != null){
next = current.next;
current.next = prev;
prev = current;
current = next;
}
head.next = prev; // *** The only change ***
}
In your constructor you have:
public LinkedList(){
// Add HEAD
head = new Node(null);
}
then, 'head' is a Node that points to nothing initially.
In the reverse function, the 'head' node don't change, you don't need to create another out. But it has to point to the correct first Node.
If the list was empty, this 'head' points to null.
If the list has only one Node, this 'head' points to it yet.
If the list has more than one Node, this 'head' has to point to the last node.
Because of this, you need to change its 'next' field.

Related

write a function to add to the end of linked list [duplicate]

I'm studying for an exam, and this is a problem from an old test:
We have a singly linked list with a list head with the following declaration:
class Node {
Object data;
Node next;
Node(Object d,Node n) {
data = d;
next = n;
}
}
Write a method void addLast(Node header, Object x) that adds x at the end of the list.
I know that if I actually had something like:
LinkedList someList = new LinkedList();
I could just add items to the end by doing:
list.addLast(x);
But how can I do it here?
class Node {
Object data;
Node next;
Node(Object d,Node n) {
data = d ;
next = n ;
}
public static Node addLast(Node header, Object x) {
// save the reference to the header so we can return it.
Node ret = header;
// check base case, header is null.
if (header == null) {
return new Node(x, null);
}
// loop until we find the end of the list
while ((header.next != null)) {
header = header.next;
}
// set the new node to the Object x, next will be null.
header.next = new Node(x, null);
return ret;
}
}
You want to navigate through the entire linked list using a loop and checking the "next" value for each node. The last node will be the one whose next value is null. Simply make this node's next value a new node which you create with the input data.
node temp = first; // starts with the first node.
while (temp.next != null)
{
temp = temp.next;
}
temp.next = new Node(header, x);
That's the basic idea. This is of course, pseudo code, but it should be simple enough to implement.
public static Node insertNodeAtTail(Node head,Object data) {
Node node = new Node(data);
node.next = null;
if (head == null){
return node;
}
else{
Node temp = head;
while(temp.next != null){
temp = temp.next;
}
temp.next = node;
return head;
}
}
If you keep track of the tail node, you don't need to loop through every element in the list.
Just update the tail to point to the new node:
AddValueToListEnd(value) {
var node = new Node(value);
if(!this.head) { //if the list is empty, set head and tail to this first node
this.head = node;
this.tail = node;
} else {
this.tail.next = node; //point old tail to new node
}
this.tail = node; //now set the new node as the new tail
}
In plain English:
Create a new node with the given value
If the list is empty, point head and tail to the new node
If the list is not empty, set the old tail.next to be the new node
In either case, update the tail pointer to be the new node
Here is a partial solution to your linked list class, I have left the rest of the implementation to you, and also left the good suggestion to add a tail node as part of the linked list to you as well.
The node file :
public class Node
{
private Object data;
private Node next;
public Node(Object d)
{
data = d ;
next = null;
}
public Object GetItem()
{
return data;
}
public Node GetNext()
{
return next;
}
public void SetNext(Node toAppend)
{
next = toAppend;
}
}
And here is a Linked List file :
public class LL
{
private Node head;
public LL()
{
head = null;
}
public void AddToEnd(String x)
{
Node current = head;
// as you mentioned, this is the base case
if(current == null) {
head = new Node(x);
head.SetNext(null);
}
// you should understand this part thoroughly :
// this is the code that traverses the list.
// the germane thing to see is that when the
// link to the next node is null, we are at the
// end of the list.
else {
while(current.GetNext() != null)
current = current.GetNext();
// add new node at the end
Node toAppend = new Node(x);
current.SetNext(toAppend);
}
}
}
loop to the last element of the linked list which have next pointer to null then modify the next pointer to point to a new node which has the data=object and next pointer = null
Here's a hint, you have a graph of nodes in the linked list, and you always keep a reference to head which is the first node in the linkedList.
next points to the next node in the linkedlist, so when next is null you are at the end of the list.
The addLast() needs some optimisation as the while loop inside addLast() has O(n) complexity. Below is my implementation of LinkedList. Run the code with ll.addLastx(i) once and run it with ll.addLast(i) again , you can see their is a lot of difference in processing time of addLastx() with addLast().
Node.java
package in.datastructure.java.LinkedList;
/**
* Created by abhishek.panda on 07/07/17.
*/
public final class Node {
int data;
Node next;
Node (int data){
this.data = data;
}
public String toString(){
return this.data+"--"+ this.next;
}
}
LinkedList.java
package in.datastructure.java.LinkedList;
import java.util.ArrayList;
import java.util.Date;
public class LinkedList {
Node head;
Node lastx;
/**
* #description To append node at end looping all nodes from head
* #param data
*/
public void addLast(int data){
if(head == null){
head = new Node(data);
return;
}
Node last = head;
while(last.next != null) {
last = last.next;
}
last.next = new Node(data);
}
/**
* #description This keep track on last node and append to it
* #param data
*/
public void addLastx(int data){
if(head == null){
head = new Node(data);
lastx = head;
return;
}
if(lastx.next == null){
lastx.next = new Node(data);
lastx = lastx.next;
}
}
public String toString(){
ArrayList<Integer> arrayList = new ArrayList<Integer>(10);
Node current = head;
while(current.next != null) {
arrayList.add(current.data);
current = current.next;
}
if(current.next == null) {
arrayList.add(current.data);
}
return arrayList.toString();
}
public static void main(String[] args) {
LinkedList ll = new LinkedList();
/**
* #description Checking the code optimization of append code
*/
Date startTime = new Date();
for (int i = 0 ; i < 100000 ; i++){
ll.addLastx(i);
}
Date endTime = new Date();
System.out.println("To total processing time : " + (endTime.getTime()-startTime.getTime()));
System.out.println(ll.toString());
}
}
The above programs might give you NullPointerException. This is an easier way to add an element to the end of linkedList.
public class LinkedList {
Node head;
public static class Node{
int data;
Node next;
Node(int item){
data = item;
next = null;
}
}
public static void main(String args[]){
LinkedList ll = new LinkedList();
ll.head = new Node(1);
Node second = new Node(2);
Node third = new Node(3);
Node fourth = new Node(4);
ll.head.next = second;
second.next = third;
third.next = fourth;
fourth.next = null;
ll.printList();
System.out.println("Add element 100 to the last");
ll.addLast(100);
ll.printList();
}
public void printList(){
Node t = head;
while(n != null){
System.out.println(t.data);
t = t.next;
}
}
public void addLast(int item){
Node new_item = new Node(item);
if(head == null){
head = new_item;
return;
}
new_item.next = null;
Node last = head;
Node temp = null;
while(last != null){
if(last != null)
temp = last;
last = last.next;
}
temp.next = new_item;
return;
}
}

Most efficient way to remove a node on a single linked list?

I am implementing a single linked list of integer and I was wondering what is the most efficient way to locate a given value and remove it from the list. This is what I have so far:
public class LinkedList {
Node head;
public void insert(int value){
Node newNode = new Node();
newNode.data = value;
newNode.next = null;
if(head==null){
head = newNode;
} else {
Node iterator = head;
while(iterator.next!=null){
iterator = iterator.next;
}
iterator.next = newNode;
}
}
public void display(LinkedList list){
Node iterator = head;
while (iterator!=null){
System.out.println(iterator.data);
iterator = iterator.next;
}
}
public void remove(LinkedList list, int value){
Node iterator = head;
while(iterator!=null){
if(iterator.next.data == value){
iterator.next = iterator.next.next;
} else{
iterator = iterator.next;
}
}
}
}
public class Node {
int data;
Node next;
}
I am adding snippet here to remove the node from SinglyLinkedList. I prefer forLoop over while; that's the reason I have added snippet with for loop.
Hope the comment in the code helps you to navigate/dry run the snippet.
public boolean remove(int value){
Node oneBeforeValueNode;
// Using for to iterate through the SinglyLinkedList
// head → is the head of your SingleLinkedList
for (Node node = head; node != null; node = node.next) {
// Compare the value with current node
if (value.equals(node.data)) {
// if matches then unlink/remove that node from SinglyLinkedList
// if its a first node in SingleLinkedList
if(oneBeforeValueNode==null){
// Considering there exists next element else SLL will be empty
head = head.next;
} else {
// if there exists next element it SLL it will attach that element with previous one
oneBeforeValueNode.next = node.next;
}
return true;
}
// Storing previous node from current
// To use it once value is found to reference it to current.next(node.next)
oneBeforeValueNode = node;
}
return false;
}
Adding with while variant as well; just to go with your flow.
public Node remove(Node head, int key) {
Node current = head;
Node previous = null;
while (current != null) {
if(current.data == key) {
if(current == head) {
head = head.next;
current = head;
} else {
previous.next = current.next;
current = current.next;
}
} else {
previous = current;
current = current.next;
}
}
return head;
}

Pass by reference value not working in java [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 5 years ago.
I am trying to write a program for quicksort using singly linked list in java.
Below is the code.
public class QuickSortInSLinkedList {
Node head;
private static class Node{
private int data;
private Node next;
Node(int data){
this.data = data;
this.next = null;
}
}
public void printList(Node head){
Node node = head;
while(node != null){
System.out.print(node.data+" ,");
node = node.next;
}
}
private Node getLastNode(Node head){
Node node = head;
while(node != null && node.next != null){
node = node.next;
}
return node;
}
public void push(int data){
Node node = new Node(data);
if(head == null){
head = node;
return;
}
node.next = head;
head = node;
}
void quickSort(Node head){
Node lastnode = getLastNode(head);
head = _quickSort(head, lastnode);
return;
}
Node _quickSort(Node low, Node high){
Node newHead = null, newTail = null;
if(low == null || low == high){
return low;
}
Node part = partition(low, high, newHead, newTail);
if (newHead != part){
Node temp = newHead;
while(temp.next != part){
temp = temp.next;
}
temp.next = null;
newHead = _quickSort(newHead, temp);
temp = getLastNode(newHead);
temp.next = part;
}
part.next = _quickSort(part.next, newTail);
return newHead;
}
private Node partition(Node low, Node high, Node newHead, Node newTail){
Node pivot = high;
Node previous = null, current = head, tail = pivot;
while(current != pivot){
if (current.data < pivot.data){
if (newHead == null)
newHead = current;
previous = current;
current = current.next;
}else{
if(previous != null)
previous.next = current.next;
Node temp = current.next;
current.next = null;
tail.next = current;
tail = current;
current = temp;
}
}
if(newHead == null){
newHead = pivot;
}
newTail = tail;
return pivot;
}
public static void main(String[] args){
QuickSortInSLinkedList list = new QuickSortInSLinkedList();
list.push(5);
list.push(35);
list.push(7);
list.push(8);
list.push(34);
list.push(23);
System.out.println("Linked list before sorting");
list.printList(list.head);
System.out.println("\n Linked list after sorting");
list.quickSort(list.head);
list.printList(list.head);
}
}
I understand that since in java we have pass by reference value, this code should work but in line 62 i.e. variables newHead and newTail is always received as null after the call to partition method.
below is the error
Exception in thread "main" java.lang.NullPointerException
23 ,34 ,8 ,7 ,35 ,5 ,
at implementation.sorting.QuickSortInSLinkedList$Node.access$100(QuickSortInSLinkedList.java:6)
Linked list after sorting
at implementation.sorting.QuickSortInSLinkedList._quickSort(QuickSortInSLinkedList.java:62)
at implementation.sorting.QuickSortInSLinkedList.quickSort(QuickSortInSLinkedList.java:47)
at implementation.sorting.QuickSortInSLinkedList.main(QuickSortInSLinkedList.java:123)
Please help me understand why is it so.
Thanks
Java does manipulate objects by reference, and all object variables are references. However, Java doesn't pass method arguments by reference; it passes them by value.

Java Double Linked List Stack Tail error

I searched for this alot found alota similar answers but nothing to help my exact problem.
I'm doing a push method for my double linked list, while the pointers on the head work fine, the tail next and previous pointers do not work please help.
public class MyStack<E> implements MyDeque {
private Node<E> head;
private Node<E> tail;
private int size;
public MyStack() {
head = null;
tail = null;
size = 0;
}
public void push(Object element) {
Node<E> newNode = new Node(element);
if(size == 0) {
Node temp = new Node(head);
head = newNode;
head.next = head;
head.previous = head;
tail = head;
tail.next = head;
tail.previous = temp;
}
else {
newNode.previous = head;
head = newNode;
newNode.next = tail;
(tail.next).previous = tail;
}//else statement
size++;
}//push()
public Object peek() {
if (size==0) return null;
else
return head;
}
public Object pop() {
size--;
if(size == 0)
return null;
else {
Node temp = new Node(head.previous);
head = head.previous;
head.next = tail;
head.previous = temp;
return head;
}//else
}//pop()
#Override
public int size() {
return size;
}
private class Node<E> {
private E data;
private Node<E> next;
private Node<E> previous;
public Node(E data) {
this.data = data;
this.next = null;
this.previous = null;
}
public Node(E data, Node<E> next, Node<E> previous) {
this.data = data;
this.next = next;
this.previous = previous;
}//constructor
public String toString() {
return data+"";
}
}//class Node<E>
public String toString() {
return (head+" Head\n" + head.next +" Head.Next\n" + head.previous+ " Head.previous\n"
+ tail+" Tail\n" + tail.next+" tail.next\n" + tail.previous+" tail.previous\n");
}
}
The case where you push an object when the stack is empty does not look correct. The first node added should be assigned to head. Then the tail becomes the new node's head, this new node becomes the tail node's tail, and the new node itself becomes the tail.
Usually in a stack you add and remove elements at the end (the tail). The code doesn't make it very clear what you are trying to do with the head and tail members. Maybe it would be clearer for you if you name them firstNode and lastNode.
I can actually see a few issues with this code
public class MyStack<E> implements MyDeque {
private Node<E> head;
private Node<E> tail;
private int size;
public MyStack() {
head = null;
tail = null;
size = 0;
}
This looks fine
public void push(Object element) {
Node<E> newNode = new Node(element);
if(size == 0) {
Node temp = new Node(head);
head = newNode;
head.next = head;
head.previous = head;
tail = head;
tail.next = head;
tail.previous = temp;
}
else {
newNode.previous = head;
head = newNode;
newNode.next = tail;
(tail.next).previous = tail;
}//else statement
size++;
}//push()
Bit confused why you are taking in an object instead of your generic E.
You really don't need the temp value here, in fact it looks like you are breaking your previous when you set tail.previous = temp
In your else you aren't setting the tail.previous correctly. The last line should be tail.previous = head. You also missed the head.next
So cleaned up a bit
public void push(E element) {
Node newNode = new Node(E);
if(size == 0) {
head = newNode;
head.next = head;
head.previous = head;
tail = head;
} else {
newNode.previous = head;
head.next = newNode;
newNode.next = tail;
tail.previous = newNode;
head = newNode;
}
size++;
}
In your pop method you probably want to move your size decrement after your size check, otherwise a 1 element stack will return null when popped.
edit: This would probably be easier with a singly linked list, or at least not a circular doubly linked list.
and adding at the end would probably be the more conventional way to do things.

Adding items to end of linked list

I'm studying for an exam, and this is a problem from an old test:
We have a singly linked list with a list head with the following declaration:
class Node {
Object data;
Node next;
Node(Object d,Node n) {
data = d;
next = n;
}
}
Write a method void addLast(Node header, Object x) that adds x at the end of the list.
I know that if I actually had something like:
LinkedList someList = new LinkedList();
I could just add items to the end by doing:
list.addLast(x);
But how can I do it here?
class Node {
Object data;
Node next;
Node(Object d,Node n) {
data = d ;
next = n ;
}
public static Node addLast(Node header, Object x) {
// save the reference to the header so we can return it.
Node ret = header;
// check base case, header is null.
if (header == null) {
return new Node(x, null);
}
// loop until we find the end of the list
while ((header.next != null)) {
header = header.next;
}
// set the new node to the Object x, next will be null.
header.next = new Node(x, null);
return ret;
}
}
You want to navigate through the entire linked list using a loop and checking the "next" value for each node. The last node will be the one whose next value is null. Simply make this node's next value a new node which you create with the input data.
node temp = first; // starts with the first node.
while (temp.next != null)
{
temp = temp.next;
}
temp.next = new Node(header, x);
That's the basic idea. This is of course, pseudo code, but it should be simple enough to implement.
public static Node insertNodeAtTail(Node head,Object data) {
Node node = new Node(data);
node.next = null;
if (head == null){
return node;
}
else{
Node temp = head;
while(temp.next != null){
temp = temp.next;
}
temp.next = node;
return head;
}
}
If you keep track of the tail node, you don't need to loop through every element in the list.
Just update the tail to point to the new node:
AddValueToListEnd(value) {
var node = new Node(value);
if(!this.head) { //if the list is empty, set head and tail to this first node
this.head = node;
this.tail = node;
} else {
this.tail.next = node; //point old tail to new node
}
this.tail = node; //now set the new node as the new tail
}
In plain English:
Create a new node with the given value
If the list is empty, point head and tail to the new node
If the list is not empty, set the old tail.next to be the new node
In either case, update the tail pointer to be the new node
Here is a partial solution to your linked list class, I have left the rest of the implementation to you, and also left the good suggestion to add a tail node as part of the linked list to you as well.
The node file :
public class Node
{
private Object data;
private Node next;
public Node(Object d)
{
data = d ;
next = null;
}
public Object GetItem()
{
return data;
}
public Node GetNext()
{
return next;
}
public void SetNext(Node toAppend)
{
next = toAppend;
}
}
And here is a Linked List file :
public class LL
{
private Node head;
public LL()
{
head = null;
}
public void AddToEnd(String x)
{
Node current = head;
// as you mentioned, this is the base case
if(current == null) {
head = new Node(x);
head.SetNext(null);
}
// you should understand this part thoroughly :
// this is the code that traverses the list.
// the germane thing to see is that when the
// link to the next node is null, we are at the
// end of the list.
else {
while(current.GetNext() != null)
current = current.GetNext();
// add new node at the end
Node toAppend = new Node(x);
current.SetNext(toAppend);
}
}
}
loop to the last element of the linked list which have next pointer to null then modify the next pointer to point to a new node which has the data=object and next pointer = null
Here's a hint, you have a graph of nodes in the linked list, and you always keep a reference to head which is the first node in the linkedList.
next points to the next node in the linkedlist, so when next is null you are at the end of the list.
The addLast() needs some optimisation as the while loop inside addLast() has O(n) complexity. Below is my implementation of LinkedList. Run the code with ll.addLastx(i) once and run it with ll.addLast(i) again , you can see their is a lot of difference in processing time of addLastx() with addLast().
Node.java
package in.datastructure.java.LinkedList;
/**
* Created by abhishek.panda on 07/07/17.
*/
public final class Node {
int data;
Node next;
Node (int data){
this.data = data;
}
public String toString(){
return this.data+"--"+ this.next;
}
}
LinkedList.java
package in.datastructure.java.LinkedList;
import java.util.ArrayList;
import java.util.Date;
public class LinkedList {
Node head;
Node lastx;
/**
* #description To append node at end looping all nodes from head
* #param data
*/
public void addLast(int data){
if(head == null){
head = new Node(data);
return;
}
Node last = head;
while(last.next != null) {
last = last.next;
}
last.next = new Node(data);
}
/**
* #description This keep track on last node and append to it
* #param data
*/
public void addLastx(int data){
if(head == null){
head = new Node(data);
lastx = head;
return;
}
if(lastx.next == null){
lastx.next = new Node(data);
lastx = lastx.next;
}
}
public String toString(){
ArrayList<Integer> arrayList = new ArrayList<Integer>(10);
Node current = head;
while(current.next != null) {
arrayList.add(current.data);
current = current.next;
}
if(current.next == null) {
arrayList.add(current.data);
}
return arrayList.toString();
}
public static void main(String[] args) {
LinkedList ll = new LinkedList();
/**
* #description Checking the code optimization of append code
*/
Date startTime = new Date();
for (int i = 0 ; i < 100000 ; i++){
ll.addLastx(i);
}
Date endTime = new Date();
System.out.println("To total processing time : " + (endTime.getTime()-startTime.getTime()));
System.out.println(ll.toString());
}
}
The above programs might give you NullPointerException. This is an easier way to add an element to the end of linkedList.
public class LinkedList {
Node head;
public static class Node{
int data;
Node next;
Node(int item){
data = item;
next = null;
}
}
public static void main(String args[]){
LinkedList ll = new LinkedList();
ll.head = new Node(1);
Node second = new Node(2);
Node third = new Node(3);
Node fourth = new Node(4);
ll.head.next = second;
second.next = third;
third.next = fourth;
fourth.next = null;
ll.printList();
System.out.println("Add element 100 to the last");
ll.addLast(100);
ll.printList();
}
public void printList(){
Node t = head;
while(n != null){
System.out.println(t.data);
t = t.next;
}
}
public void addLast(int item){
Node new_item = new Node(item);
if(head == null){
head = new_item;
return;
}
new_item.next = null;
Node last = head;
Node temp = null;
while(last != null){
if(last != null)
temp = last;
last = last.next;
}
temp.next = new_item;
return;
}
}

Categories