The following code ensures that elements are inserted in a linked list in a sorted manner.
After understanding the logic behind this i decided to test it on my own. However when i wrote my version of the code it as follows.
public class SortedList {
private Node first;
public SortedList() {
first = null;
}
public boolean isEmpty() {
return first == null;
}
public void insert(int j) {
Node newNode = new Node(j);
Node previous = null;
Node current = first;
while (current != null && j > current.iData) {
previous = current;
current = current.next;
}
if (previous == null)
first = newNode;
else
newNode.next = current;
previous.next = newNode;
}
public Node remove() {
Node temp = first;
first = first.next;
return temp;
}
public void displayList() {
System.out.println("First to -----> Last");
Node current = first;
while (current != null) {
current.display();
current = current.next;
}
}
}
NODE CLASS
public class Node {
public int iData;
public Node next;
public Node(int id) {
iData = id;
}
public void display() {
System.out.println(iData + " ");
}
}
TEST CLASS
public class SortedListApp {
public static void main(String[] args) {
SortedList list = new SortedList();
list.insert(20);
list.insert(40);
list.displayList();
list.insert(10);
list.insert(30);
list.insert(50);
list.displayList();
list.remove();
list.displayList();
}
}
The only difference between the two is that in my version when the while loop terminates. I first set the next value of the newNode to the current and then i set the next value of previous to the new Node. In the original code posted they have it reversed. For some reason this throws Null Pointer Exception. I am wondering why?
From what i understand, once the new node finds its place for insertion. We have reference to the previous node and the current node and we are trying to insert the new node in the middle of the previous and the current. Therefore what i do is set the next of the new Node to the current and then i set the next of previous node to the new node.
Please tell me where i am wrong.
Trace through this code when previous is null:
if (previous == null)
first = newNode;
else
newNode.next = current;
previous.next = newNode;
Notice that you never actually changed previous in the if statement, so this will try to write the next field of null, causing the crash.
If previous is null, then you need to prepend the node to the list, and in that case all you need to do is set first to newNode and make newNode's next pointer point to the old list. In the case where previous isn't null, then you need to do two rewirings: you need to make previous.next point to the new node and for the new node's next pointer to point to the current node. You can fix this by writing
if (previous == null) {
newNode.next = current;
first = newNode;
}
else {
newNode.next = current;
previous.next = newNode;
}
Equivalently:
newNode.next = current;
if (previous == null)
first = newNode;
else
previous.next = newNode;
Hope this helps!
Related
How can I add it and delete Node First and delete Node Last in a double-link list
Just want to add delete Node First and delete Node Last. I did not know how to add it in your programming, but I want to help it solve it
i have 3 class
class node .
class doublyLinkedListMain .
class doublyLinkedList .
I want to add special programming in class doublyLinkedList this one delete Node First and delete Node Last
class doublyLinkedList
{
Node head;
public void push(int newdata)
{
Node NewNode = new Node(newdata);
NewNode.next = head;
NewNode.prev = null;
if (head != null) head.prev = NewNode;
head = NewNode;
}
public void insertAfter(Node PrevNode, int newdata)
{
if (PrevNode == null)
{
System.out.println("The given previous node cannot be null");
return;
}
Node NewNode = new Node(newdata);
NewNode.next = PrevNode.next;
PrevNode.next = NewNode;
NewNode.prev = PrevNode;
if (NewNode.next != null)
NewNode.next.prev = NewNode;
}
public void append(int newdata)
{
Node NewNode = new Node(newdata);
Node last = head;
NewNode.next = null;
if (head == null)
{
NewNode.prev = null;
head = NewNode;
return;
}
while (last.next != null) last = last.next;
last.next = NewNode;
NewNode.prev = last;
return;
}
void insertBefore(Node NextNode, int newdata)
{
if (NextNode == null)
{
System.out.println("the given next node cannot be NULL");
return;
}
Node NewNode = new Node(newdata);
NewNode.data = newdata;
NewNode.prev = NextNode.prev;
NextNode.prev = NewNode;
NewNode.next = NextNode;
if (NewNode.prev != null)
NewNode.prev.next = NewNode;
else head = NewNode;
}
void deleteNode( Node del)
{
if (head == null || del == null) return;
if (head == del) head = head.next;
if (del.next != null) del.next.prev = del.prev;
if (del.prev != null) del.prev.next = del.next;
return;
}
void printList()
{
Node n = head;
while (n != null)
{
System.out.print(n.data+" ");
n = n.next;
}
System.out.print(" \n ") ;
}
}
sorry, but you have different mistakes in your code. Firstly, for a list you need two or three pointers as attribute in your List class (Node head /* begin */, tail /* end */, current /* yes, the current element on which you have access */ - I have learned it with a current pointer but depending on your implementation you can do it without it too). Because of that, you must change some of your code. For example, you need a hasAccess() : boolean method, if you use a current pointer, which return current != null and your methods must consider and use tail. Furthermore, you should add a method isEmpty():
public boolean isEmpty() {
return head == null;
}
This method checks if the list is empty. In the case, that the list is empty (the method returns true), you cannot do some things, but you had seen that yet. But, because of the new pointer tail, you have its much easier to delete the last Node (see below).
Please, change all your attributes to private and code a getter and a setter for each of them. For example in the class Node for the attribute next:
private Node next;
// other code...
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
I have solved the problem with "delete Node First and delete Node Last" in the following way:
public class DoublyLinkedList {
private Node head; // begin
private Node tail; // end
public void deleteFirstElement() {
if (!isEmpty()) {
head = head.getNext();
}
}
public void deleteLastElement() {
if (!isEmpty()) {
tail = tail.getPrev();
}
}
// other code
}
Of course, you have to proof your other code, if it works. I hope that I could help you.
(In the insert method): In the else statement, I don't understand how "front.next" is getting updated with the line: "prev.next = newNode". Theoretically, I understand it, but practically, although "prev" gets its value from "curr", which got its value from "front" itself, there is no way that front is getting updated because "prev". How are they talking to each other?
(Insert method)I have tried debugging and when it reaches the else statement that executes => prev.next = newNode; front.next gets updated as well which I just don't understand since front is nowhere being initialised again. Front is an object of itself.
public class SinglyLinkedList<T>
{
// inner class being created:
protected class Node<T extends Comparable<T>>
{
T val;
Node<T> next;
Node(T val)
{
this.val = val;
this.next = null;
}
Node(T val, Node n)
{
this.val = val;
this.next = n;
}
}
private Node front, tail;
public SinglyLinkedList()
{
this.front = this.tail = null;
}
// print method:
public void print()
{
// print the contents of the list
Node curr = front;
while (curr != null)
{
System.out.println(curr.val + " ");
curr = curr.next;
}
}
// insert method:
public void insert(T val)
{
Node newNode = new Node((Comparable) val);
// make a new node
if (front == null)
{
// empty list
front = tail = newNode;
}
else
{
// list is not empty
Node curr = front, prev = null;
// look for insert point.
while (curr != null && curr.val.compareTo(val) < 0)
{
prev = curr;
curr = curr.next;
}
// insert node before curr
newNode.next = curr;
if (curr == front)
{
// update front
front = newNode;
}
else
{
// update node before
prev.next = newNode;
}
if (tail.next != null)
{
// move tail to last node
tail = tail.next;
}
}
}
}
I expected curr to keep continuing to fill in the chain of nodes using curr.next and using "prev" as a temporary node used in the process of adding a node in between two nodes.
I also didn't expect print method to work since it begins with front node. Theoretically, it does make sense to start with front node, but looking at my code how "front" is not equalling to any value, but rather "curr" equalling "front", makes me feel that "front" shouldn't be having the access to the rest chain of nodes.
I expected "front.next" to be null, but it isn't.
Well, according to your code, the front works as the first node of the linked list, it actually equals to a certain value (a real node) because your code set it to be so a
if (front == null)
{
// empty list
front = tail = newNode;
}
and
if (curr == front)
{
// update front
front = newNode;
}
See! You indeed pointed it to a certain node with a given value.
For the update question. I think possibly you are always inserting a new node right next to the front node. Under that circumstance, the prev points to the same node as the front do. So if you update prev, you are updating front, too!
public void insertBefore(T e) {
if(empty())
{
insert(e);
}
else
{
if(head == current)
{
current.next = new Node<T>(current.data);
current.data = e;
}
else
{
Node<T> oldCurrent = current;
Node<T> newNode = new Node<T>(e);
current = head;
while(current != oldCurrent)
current = current.next;
newNode.next = oldCurrent;
current.next = newNode;
current = current.next;
}
}
}
insertBefore(T e): requires: list L is not full. input: e. results: a new node
containing element e is created and inserted before the current element in the list.
The new element e is made the current element. If the list is empty e is inserted at
the beginning and also made the head element. output: none
insert() method implmention
public void insert(T e) {
Node<T> tmp;
if (empty()) {
current = head = new Node<T> (e);
}
else {
tmp = current.next;
current.next = new Node<T> (e);
current = current.next;
current.next = tmp;
}
}
I'm implementing this method as an implementer
the class Linked List has two nodes a current node and a head when we insert a node the current moves to the newest node added to the list.. and the method retrieve returns the current data in the Current node
My Questions is when i type the following in my main so i can test my Linked List implemention of this method i'm not getting the results which i intended my method so
l.insert(2);
l.insert(3);
l.insert(4);
l.insertBefore(5);
l.findFirst();
for(int i = 0; i < 4 ; i++)
{
System.out.print(l.retrieve());
l.findNext();
}
the result of my Testing : 2345
intended results : 2354
If current != head, you should find the previous node of the current, not current itself. like this:
Node<T> prev = head;
while (prev.next != current) {
prev = prev.next;
}
prev.next = new Node<T>(e);
prev.next.next = current;
I'm working on a method that is supposed to delete the node prior to the last one,the logic seems quite fine with me, but when I tried to implement it in a project, it didn't work out. ( Oh and I'm using MyLinkedList)
here's the code:
public void deleteSec(){
Node current = head;
Node p = head.next;
Node q = null;
while(p.next!=null){
q = current;
current.next = p;
p = p.next;
}
q.next = p; // q.next = q.next.next;
}
What if your LL is empty? head will be null and this will cause an exception when you call head.next;
you have to take care of special cases like: empty LL, LL with one node, LL with two nodes.
Here is my code:
public void deleteSec() {
if (head == null) {
return;
}
if (head.next == null) {
return;
}
if (head.next.next == null) {
head = head.next;
return;
}
Node current = head;
Node p = current.next;
Node q = p.next;
while (q.next != null) {
current = current.next;
p = p.next;
q = q.next;
}
current.next = q;
}
if(myLinkedList.size() > 1) {
myLinkedList.remove(myLinkedList.size()-2);
}
well i personally compiled it,
Assuming the node class is named Node and you have a getNext() method that returns the next Node or null if this Node is the last node, you would do something like this.
if (head == null) // or if (first == null)
{
return; // There are no elements in the list.
}
Node currect = head; // This is the head, or Node current = first;
Node previous = null;
while (current.getNext() != null)
{
previous = current;
currrent = current.getNext();
}
Then do this to make the second to last pointer to next null.
if (previous != null)
{
previous.setNext( null );
}
else
{
// The list has 1 entry only.
head = null; // or first = null;
}
If deleting a second last node would be a common operation, as it is in my case, I would suggest an extra prev or previous node added to the Node construction.
Usually a linked list node would be
private static class Node<Item> {
private Item item;
private Node<Item> next;
}
But I modified it to be like
private static class Node<Item> {
private Item item;
private Node<Item> prev;
private Node<Item> next;
}
Thus, if you want to delete the second last, the implementation would be pretty straightforward:
oldSecondLast = last.prev; // Assumes last points to the last node
oldSecondLast.next = last;
last = oldSecondLast.prev;
oldSecondLast = null; // To avoid loitering
Data structures class, implementing a singly linked-list with head, tail and current nodes. Having trouble with a method, could use a nudge in the right direction.
From the assignment, write the method:
add( item ) : adds the item (String) after the current node in the list and sets the current pointer to refer to the new node.
My attempt:
public void add(String item)
{
if(curr != null)
{
Node newNode = new Node(item, curr.next);
curr.next = newNode;
curr = newNode;
}
else
{
head = tail = new Node(item, null);
curr = head;
}
}
My add method only seems to work when I'm adding items to the middle of the list, not on either end. If I use it to add a few items and then print the list, only the first one I added will be on the list, while my prepend and append methods have tested just fine.
Is there any glaring issue with my code? I feel like I'm missing something obvious.
All:
public class LinkedList {
Node head = null; /* Head of the list */
Node tail = null; /* Tail of the list */
Node curr = null; /* Current node in the list */
public void prepend(String item) {
if (head == null) {
head = tail = new Node(item, null);
curr = head;
} else {
head = new Node(item, head);
curr = head;
}
}
public void append(String item) {
if (head == null) {
head = tail = new Node(item, null);
curr = tail;
} else {
tail.next = new Node(item, null);
tail = tail.next;
curr = tail;
}
}
public void add(String item) {
if (curr != null) {
Node newNode = new Node(item, curr.next);
curr.next = newNode;
curr = newNode;
} else {
head = tail = new Node(item, null);
curr = head;
}
}
public void delete() {
if (curr.next == null) {
Node temp = head;
while (temp.next != curr) {
System.out.println(temp.item);
temp = temp.next;
}
temp.next = null;
curr = head;
}
}
public void find(String item) {
Node temp = new Node(curr.item, curr.next);
if (item.equals(temp.item))
curr = temp;
else {
temp = temp.next;
while (temp.next != null && temp != curr) {
if (item.equals(temp.item))
curr = temp;
}
}
}
public String get() {
if (curr != null)
return curr.item;
else
return "";
}
public boolean next() {
if (curr != tail) {
curr = curr.next;
return true;
} else
return false;
}
public void start() {
curr = head;
}
public void end() {
curr = tail;
}
public boolean empty() {
if (head == null)
return true;
else
return false;
}
}
Node class:
class Node {
Node next;
String item;
Node(String item, Node next) {
this.next = next;
this.item = item;
}
}
There is indeed a problem in add: it doesn't update tail when nodes already exist. Consider this sequence of actions:
LinkedList list = new LinkedList();
list.add("one");
list.add("two");
list.append("three");
If you were to then print it using this:
public void print() {
Node curr = this.head;
while(curr != null) {
System.out.println(curr.item);
curr = curr.next;
}
}
Like this:
list.print();
You'd get the following output:
one
three
This happens because tail -- which append relies on -- continues to point to the first Node after the second add operation is performed.
I don't see any problems here, so I would guess the issue is elsewhere.
Okay, the only issue I see there is in delete:
public void delete()
{
Node temp = head;
while(temp != null && temp.next != curr) {
System.out.println(temp.item);
temp=temp.next;
}
if (temp != null && temp.next != null) {
temp.next = temp.next.next;
}
curr = head;
}
I think I have found your problem.
If you use append() you add it directly after the tail. But when you have added previous nodes after the tail you don't set your tail to the new node. This means that once you call append() twice you loose all the nodes that you have added after the first append().
Brief example:
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.add("First add");
list.append("First Append");
list.add("Second add");
list.prepend("First prepend");
list.add("Third add");
list.prepend("Second prepend");
list.add("fourth add");
list.append("Second Append");
list.add("Fifth add");
list.add("Sixth add");
list.start();
do {
System.out.println(list.get().toString());
} while (list.next());
}
Output:
Second prepend
fourth add
First prepend
Third add
First add
First Append
Second Append
Conclusion: "Second Add" is lost, as well as "Fifth add" and "Sixth add" because your next() method stops as soon as it reaches the tail. You need to always update the tail if you add a new node in the end.
Hope this helps.
Cheers, Chnoch
I think the problem is
if (curr != null) {
Node newNode = new Node(item, curr.next); //<-- here (curr.next)
//and
Node(String item, Node next) {
this.next = next; //<-- here
Try (Edited):
Node newNode = new Node(item, curr); // pass curr to the constructor of Node
curr = newNode;