Here is my complete Java source code for implementing a singly linked list. I have seen many tutorials where they have been talking about inserting a node at the beginning. So, I decided to add a method insertAfterNode(int y) in my code where I can add data inside a node after a particular node.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package datastructures;
/**
*
* #author Administrator
*/
public class Link {
int data;
Link next;
public Link(int d) {
this.data = d;
}
public void display() {
System.out.println(data);
}
public static class LinkedList {
Link first;
public void insertItemFirst(int x){
Link newLink = new Link(x);
newLink.next = first;
first = newLink;
}
public Link deleteFirst() {
Link temp = first;
first = first.next;
return temp;
}
public void displayList() {
Link current = first;
while (current != null) {
current.display();
current = current.next;
}
}
// START Of METHOD
public void insertAfterNode(int y) {
// Considering LinkedList is Sorted
Link newNode = new Link(y);
Link current = first;
while (current != null) {
while (current.data < y) {
current = current.next;
newNode.next = current;
current = newNode;
}
}
}
//END Of METHOD
}
public static void main(String[] args) {
LinkedList addelements = new LinkedList();
addelements.insertItemFirst(20);
addelements.insertItemFirst(30);
addelements.insertItemFirst(40);
addelements.insertItemFirst(50);
addelements.insertAfterNode(44);
addelements.displayList();
System.out.println("After Calling Deletion Method Once ");
addelements.deleteFirst();
addelements.displayList();
}
}
The above code keeps on running in Netbeans and I had to stop the build to exit from it. I believe there is something wrong with my method implementation. Please let me know what's wrong with my following method:
public void insertAfterNode(int y) {
// Considering LinkedList is Sorted
Link newNode = new Link(y);
Link current = first;
while (current != null) {
while (current.data < y) {
current = current.next;
newNode.next = current;
current = newNode;
}
}
}
The code runs just fine without above method.
The current Link reference changes only if the y value is greater than the current.data. If the fist.data is, say, 10, and the y is 5, your code will never terminate.
You have to modify your while(current != null) cycle. Do not use the inner while.
Link newNode = new Link(y);
// "first" requires a special treatment, as we need to replace the "first" value
if(first.data > y){
// insert the new Link as first element
newNode.next = first;
first = newNode;
} else {
// we need the previous Link, because previous.next will be set to the newNode
Link previous = first;
Link current = first.next;
while (current != null) {
if(current.data < y) {
previous = current;
current = current.next;
} else {
// we insert newNode between previous and current
// btw. what should happen if current.data == y?
previous.next = newNode;
newNode.next = current;
break; // we are done, quit the cycle
}
}
// if the newNode.next is null at this point, means we have not inserted it yet.
// insert it as the last element in the list. previous is pointing at it.
if(newNode.next == null){
previous.next = newNode;
}
} // end of else
P.S. I hope it works, I have not tested the code :)
Related
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;
}
}
I'm on HackerRank and I need to remove duplicate items from a sorted linked list. I passed all the cases except for two of them which the input is something like: 10001102034
So my program takes to seconds to complete and exceed the time. How can I do my code more efficiently, I heard about using square root but I don't know how to use it. Any guide is appreciate. Here is my code.
private static Node removeDuplicates(Node head) {
/* Another reference to head */
Node current = head;
Node next;
/* Traverse list till the last node */
while (current != null && current.next != null) {
if (current.data == current.next.data) {
next = current.next.next;
if (next == null) {
current.next = null;
break;
}
current.next = next;
} else {
current = current.next;
}
}
return head;
}
Again. It works but takes too much times with longer numbers.
You should replace condition if (current.data == current.next.data) with while loop and use break 'label':
out:
while (current != null && current.next != null) {
while (current.data == current.next.data) {
next = current.next.next;
if (next == null) {
current.next = null;
break out;
}
current.next = next;
}
current = current.next;
}
You can't use the square root because when u want to remove duplicates from a list you have to check all the list .
The square root technique is used for searching in a sorted list.
But for your question if you can improve the runtime on that your code in O(n^2) but if you change your code to use hashtable you can make it O(n).
import java.util.HashSet;
public class removeDuplicates
{
static class node
{
int val;
node next;
public node(int val)
{
this.val = val;
}
}
/* Function to remove duplicates from a
unsorted linked list */
static void removeDuplicate(node head)
{
// Hash to store seen values
HashSet<Integer> hs = new HashSet<>();
/* Pick elements one by one */
node current = head;
node prev = null;
while (current != null)
{
int curval = current.val;
// If current value is seen before
if (hs.contains(curval)) {
prev.next = current.next;
} else {
hs.add(curval);
prev = current;
}
current = current.next;
}
}
/* Function to print nodes in a given linked list */
static void printList(node head)
{
while (head != null)
{
System.out.print(head.val + " ");
head = head.next;
}
}
I hope this will help you.
I believe I have the code on how to remove an item in a linked list but I'm not sure how I can make it so that all occurrences of a value would be removed. Where would I need to make some changes that would have it check through all the values in the list?
I've tried to make an alternate or a dummy that pointed to the head but I wasn't sure where I was going with that.
public class LinkList {
private Link first; // ref to first link on list
// -------------------------------------------------------------
public LinkList() // constructor
{
first = null; // no links on list yet
}
// -------------------------------------------------------------
public void insertFirst(int id, double dd) {
Link newLink = new Link(id, dd);
newLink.next = first; // it points to old first link
first = newLink; // now first points to this
}
// -------------------------------------------------------------
public Link find(int key) // find link with given key
{ // (assumes non-empty list)
Link current = first; // start at 'first'
while (current.iData != key) // while no match,
{
if (current.next == null) // if end of list,
{
return null; // didn't find it
} else // not end of list,
{
current = current.next; // go to next link
}
}
return current; // found it
}
// -------------------------------------------------------------
public void displayList() // display the list
{
System.out.print("List (first-->last): ");
Link current = first; // start at beginning of list
while (current != null) // until end of list,
{
current.displayLink(); // print data
current = current.next; // move to next link
}
System.out.println("");
}
// -------------------------------------------------------------
public Link removeAll(int n) // delete link with given key
{ // (assumes non-empty list)
Link current = first; // search for link
Link previous = first;
while (current.iData != n) {
if (current.next == null) {
return null; // didn't find it
} else {
previous = current; // go to next link
current = current.next;
}
}
if (current == first) // if first link,
{
first = first.next; // change first
} else // otherwise,
{
previous.next = current.next; // bypass it
}
return current;
}
}
I expect to have all the values deleted for a given key but it I'm only able to delete one instance of a given value.
This removes all occurrences of Link with id == n. It should be the same if you want to remove by Link.iData.
public Link removeAll(int n)
{
Link head = first;
Link previous = null;
Link current = first;
while (current != null) {
if (current.id == n) {
if (previous == null) {
head = current.next;
} else {
previous.next = current.next;
}
} else {
previous = current; // if we removed current, let previous remain the same
}
current = current.next;
}
first = head;
return head;
}
Running the code like this:
LinkList l = new LinkList();
l.insertFirst(0, 0.1);
l.insertFirst(3, 3.1);
l.insertFirst(1, 1.1);
l.insertFirst(3, 3.1);
l.insertFirst(2, 2.1);
l.displayList();
l.removeAll(3);
l.displayList();
Outputs:
List (first-->last):
2 : 2.1
3 : 3.1
1 : 1.1
3 : 3.1
0 : 0.1
List (first-->last):
2 : 2.1
1 : 1.1
0 : 0.1
I have this class called ListNode, similar to yours.
public class ListNode {
public ListNode next;
public int val;
public ListNode removeAll(int n) {
ListNode newHead = null;
ListNode node = this;
//for keeping track of the node previous to the current node
ListNode prev = null;
//loop through the entire linked list
while (node != null) {
//when you encounter the val == n, delete the node
if (node.val == n) {
if (prev != null){
//this makes the previous node to point the node to the next of the current node
//if 2 -> 1 -> 3 and we have to remove node with key 1 and current node val == 1
// the following code will do this
// 2 -> 3
prev.next = node.next;
}
ListNode next = node.next;
//taking the same example
//this code will break the link : 1->3
node.next = null;
node = next;
} else {
if (newHead == null) {
newHead = node;
}
prev = node;
node = node.next;
}
}
return newHead;
}
}
You, basically, have to traverse through whole linked list, keeping track of the previous node for the current node and when you find a node with value/key/data equal to n, you make the previous node point to the next node of the current node and break the link of the current node to the next node.
Let's first start without deleting anything. To delete all occurrences, you first need to be able to iterate over the entire list (so you can look for multiple matches). Iterating over the whole list would simply be:
public void removeAll(int n) // delete link with given key
{
Link current = first;
Link previous = first;
while (current != null)
{
// simply move to the next Link
previous = current; // store the current node as the previous for the next iteration
current = current.next; // move to the next link
}
}
Next, let's add in a check to see if the current Link is one that should be deleted:
public void removeAll(int n) // delete link with given key
{
Link current = first;
Link previous = first;
while (current != null)
{
if (current.iData == n)
{
// To do...delete the current Link
}
else
{
// simply move to the next Link
previous = current; // store the current node as the previous for the next iteration
current = current.next; // move to the next link
}
}
}
Once we've found a match, there are two possibilities. Either the Link is the first Link, or it is somewhere further down in the list:
If the link is the first one, then we move current to the next Link, and make both first and previous point to the new current Link.
If we are not the first Link, then we move current to the next Link, and update the previous.next field to point to the new current Link (thus skipping over the Link to delete).
Here's the updated code:
public void removeAll(int n) // delete link with given key
{
Link current = first;
Link previous = first;
while (current != null)
{
if (current.iData == n)
{
if (current == first)
{
current = current.next;
first = current;
previous = current;
}
else
{
current = current.next;
previous.next = current;
}
}
else
{
// simply move to the next Link
previous = current;
current = current.next;
}
}
}
Here is simple recursive implementation (this implementation leaves initial list intact, and creates new without specified element):
public class Answer {
public static void main(String[] args) {
LinkedList list = new LinkedList(1, new LinkedList(2, new LinkedList(1, new LinkedList(2, new LinkedList(3, null)))));
System.out.println(list);
LinkedList withoutOne = list.removeAll(1);
System.out.println(withoutOne);
LinkedList withoutTwo = list.removeAll(2);
System.out.println(withoutTwo);
LinkedList withoutThree = list.removeAll(3);
System.out.println(withoutThree);
}
}
class LinkedList {
private int value;
private LinkedList next;
public LinkedList(int value, LinkedList next) {
this.value = value;
this.next = next;
}
public LinkedList removeAll(int value) {
if (this.next == null) {
return (this.value == value) ? null : new LinkedList(this.value, null);
} else if (this.value == value) {
return this.next.removeAll(value);
} else {
return new LinkedList(this.value, this.next.removeAll(value));
}
}
#Override
public String toString() {
String res = "LinkedList:";
for (LinkedList link = this; link != null; link = link.next) {
res += " " + link.value;
}
return res;
}
}
I was reading about queues in java implementation. I want to implement the following task:
public class DoublyLinkedList
{
private Node first; // the first Node in the list
private Node last; // the last Node in the list
private class Node
{
private Point p;
private Node prev; // the previous Node
private Node next; // the next Node
}
public void reverse()
{
// your code
}
}
I did like this:
public void reverse() { // that reverses the order of the entire list
if (first == null && last == null) {
throw new RuntimeException();
}
Node current = first;
while (current!=null) {
current.next= current.next.prev;
current.prev=current.prev.next;
current=current.next;
}
}
Am I doing right?
thanks
You don't change the first and last pointer in your code. Why are you throwing an exception if the list is empty?
I guess I would do something like:
public void reverse()
{
Node current = first;
while (current != null) {
Node next = current.next;
current.next = current.prev;
current.prev = next;
current = next;
}
Node temp = first;
first = last;
last = temp;
}
No it is not. current.next = current.next.prev is like current.next = current and current.prev = current.prev.next is like current.prev = current. Please attach a debugger and follow your code to find the errors and the right solution. We won't do your homework here. ;-)
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;
}
}