How to shift elements after adding in Doubly Linked List - java

I have added an element to a specified position in a Doubly Linked List, but I want to shift all the elements that was at that position and after it to the right? Any tips on how to approach this problem?
public void addFirst(E e){
DNode<E> headerNext = header.getNext();
DNode<E> tempN = new DNode <E>(e, header, headerNext);
headerNext.setPrev(tempN);
header.setNext(tempN);
size++;
}
public void add(int pos , E e ){
DNode<E> ptr = new DNode<E> (e, null, null);
if(pos == 1){
addFirst(e);
return;
}
DNode<E> optr = header;
for (int i = 2; i <= size; i++) {
if (i == pos) {
DNode<E> tempN = optr.getNext();
ptr.setNext(ptr);
ptr.setPrev(optr);
ptr.setPrev(tempN);
tempN.setPrev(ptr);
}
ptr = ptr.getNext();
}
size++ ;
}
}

Based example in your comment:
You need to update the next pointer of new node to point to element 3's address
Element 3's previous pointer to new node address
New node previous address with element 3's previous address
Lastly Goto element 3's previous address(node) and update its next pointer to new node address.

Any tips on how to approach this problem?
Since you asked for tips on how to get started and you already have a doubly linked list here is a simple example.
Given the following is a Node in a Doubly Linked List.
// Doubly Linked list Node
class Node {
int data;
Node prev;
Node next;
// Constructor to create a new node
// next and prev is by default initialized as null
Node(int d) { data = d; }
}
The following method can be implemented for your doubly linked list. You would provide a Node that would have a new Node inserted after the Node that you provide and the next and prev pointers for the current Node and the newly added Node would all be updated to reflect the newly added Node.
/* Given a node (currentnode). insert a new node after the given
node(currentNode) */
public void InsertAfterNode(Node currentNode, int newData)
{
// check if the given current node is NULL
if (currentNode == null) {
System.out.println("The given current node cannot be NULL ");
return;
}
// allocate node
// put in the data
Node new_node = new Node(newData);
// Make next of new node as next of current node
new_node.next = currentNode.next;
// Make the next of current node as new_node
currentNode.next = new_node;
// Make current node as previous of new_node
new_node.prev = currentNode;
// Change previous of new_node's next node
if (new_node.next != null)
new_node.next.prev = new_node;
}
You could implement a similar method, in reverse, to insert a new Node before the specific Node.

Related

Doubly linked list: adding a node at front. From geeksforgeeks (java code)

This is a code that adds a node at the front of the doubly linked list. What I don't understand here is step 4. Right here, it appears to me that it's storing the address of the new_Node into the variable head.prev. The variable head.prev will now hold new-node. This doesn't even make sense because the variable 'head' will also hold new_node. So now we have two variables pointing to the same address.
Even if, in any case, this code was meant to say, new_node = head.prev, that also does not make sense, because the head.prev will be null at this point, and new_node will then point to a null.
// Class for Doubly Linked List
public class DLL {
Node head; // head of list
/* Doubly Linked list Node*/
class Node {
int data;
Node prev;
Node next;
// Constructor to create a new node
// next and prev is by default initialized as null
Node(int d) { data = d; }
}
// Adding a node at the front of the list
public void push(int new_data)
{
/* 1. allocate node
* 2. put in the data */
Node new_Node = new Node(new_data);
/* 3. Make next of new node as head and previous as NULL */
new_Node.next = head;
new_Node.prev = null;
/* 4. change prev of head node to new node */
if (head != null)
head.prev = new_Node;
/* 5. move the head to point to the new node */
head = new_Node;
}
}
The step 4 is needed to connect the prev of the old head to the new head.
This is the situation after step 3:
Then after step 4 the prev of the old head (which was null) is set to point to the new head:
And then step 5 makes head point to the new node (the new head):
If head.prev != null then head is not the first element of the list. This should be checked as a pre-condition, and an IllegalStateException should be thrown. Further processing of the insertion is senseless as the pointer to the first position must be restored.
After step 3, the new_node setup is complete, and the new_node is linked unidirectional by new_node.next to the former first, now second element head. To make the double-link complete, head.prev must be set to the new predecessor head. That is what step 4 does if you omit the if.
public class DLL {
private Node head;
private Node tail;
public void addFirst(int val) {
Node node = new Node(val);
if (head == null)
tail = node;
else {
node.next = head;
head.prev = node;
}
head = node;
}
public void addLast(int val) {
Node node = new Node(val);
if (tail == null)
head = node;
else {
tail.next = node;
node.prev = tail;
}
tail = node;
}
private static final class Node {
private final int val;
private Node prev;
private Node next;
public Node(int val) {
this.val = val;
}
}
}

Keeping a LinkedList always sorted

I've been given a code as shown below for practice purpose, and my task is to modify it so that the linked list is always sorted. My main problem now is that I have no idea where to start or what methods are to be modified. Any hints are welcome.
import java.util.Iterator;
import java.util.NoSuchElementException;
/
* This is a copy of the LinkedList class, which has been modified to only
* accept elements that can be compared.
*
* Note that the elements accepted by this list must implement the Comparable
* interface. This means that the elements can be compared as follows:
*
* x.compareTo(y) == 0 means x == y
* x.compareTo(y) < 0 means x < y
* x.compareTo(y) > 0 means x > y
*
* Your task is to modify this class so that the elements always are sorted.
*/
public class SortedLinkedList<T extends Comparable<T>> implements Iterable<T> {
/* Easy operations for a linked list
add(x): Searching for the place where the element x is to be added must
take place in the calling routine. This must set previous to
point to the node AFTER which the new element is to be inserted.
curr is set to point to the new element.
remove(): The curr element is removed from the list. Searching for this
element must take place in the calling routine. This must set
curr to point to the element to be removed. After removal curr
points to the element following the removed one.
isEmpty(): checks for an empty list
endOfList(): checks whether curr has reached and passed the end of the list
retrievecurr(): return the info part of the curr element.
reset(): resets the list so that curr points to the first element
succ(): an iterator, moves curr one step forward
Note that when a class implements the interface Iterable<T> then
it can be the target of the "foreach" statement. See IterationExample.java
*/
private Node start, curr, prev;
public SortedLinkedList() {
curr = null; // the curr position in the list
start = null; // the first element
prev = null; // the node before curr
}
public void add(T x) {
if (start == null) { // if start == null, insert a first element into an empty list
Node newNode = new Node(); // create the new element, info and link are set to null.
newNode.info = x; // and assign the data given as parameter. The link is left as null
start = newNode; // start is updated to point to the new element
curr = start; // curr is updated to point to the new first (and only) element
} else if (prev == null) { // a new first element is inserterd into a non-empty list
Node newNode = new Node(); // a new node is created ...
newNode.info = x; // and assigned the data given as parameter
newNode.link = start; // and linked before the old first element
start = newNode; // start is updated to point to the new first element
curr = newNode; // curr is updated to point to the new first element
} else { // a new element is inserted last (if prev.link == null) or between prev and curr
Node newNode = new Node(); // create a new node
newNode.info = x; // assign it the data given as parameter
newNode.link = prev.link; // link it before curr ...
prev.link = newNode; // ... and after previous
curr = newNode; // update curr to point to newNode
}
} // add
public void remove() { // removes the current node
if (isEmpty() || endOfList()) { // no node to be removed
return;
}
else { // curr points to the element to be removed
if (prev == null) { // remove a first element: start is updated!
start = start.link; // "jump over" the first element (curr/start)
curr = start; // update curr to point to the new start
}
else { // the element to be removed is in the middle of the list/last
prev.link = curr.link; // "jump over it!"
curr = curr.link; // curr is updated to the element after the removed one
}
}
} // remove
public boolean isEmpty() { // checks if the list is empty
return start == null;
}
public T retrieveCurr() { // return the curr element's data
return curr.info;
}
public void reset() { // resets a list so that curr points to the first element
curr = start; // curr starts from the beginning of the list
prev = null; // there is no previous element for curr
}
public boolean endOfList() { // has curr reached and passed the end of the list?
return curr == null;
}
public void succ() { // moves curr to the next element
curr = curr.link; // curr is set to the next node
if (prev == null) { // previous must follow; if it was null to begin with ...
prev = start; // ... it must now point to start
}
else {
prev = prev.link; // otherwise it is just moved one step forward
}
}
public Iterator<T> iterator(){ //Needed to implement the iterable interface
return new ListIterator();
}
private class Node {
T info;
Node link;
Node() {
info = null;
link = null;
}
}
/*
* An example iterator class to walk through the list from
* the start to the end. Note the similarity with the methods
* above. They implement similar functionality, but here it
* is hidden behind a standard interface.
*
* Note the class is private and the implementation of the iterator
* is therefore not visible outside.
*
* See the java api documentation for more information on
* how iterators should behave.
*/
private class ListIterator implements Iterator<T>{
private Node curr;
public ListIterator(){
curr=start;
}
public boolean hasNext(){
return curr!=null;
}
public T next(){
if(curr==null){
throw new NoSuchElementException();
}
T value=curr.info;
curr=curr.link;
return value;
}
public void remove(){
throw new UnsupportedOperationException();
}
}
}
I think the only big change in implementation which you have to make is to keep the list sorted as you insert elements. Note that the reverse operation, namely removing elements, doesn't need to change, because you are simply throwing things away which would not change any order in the list.
The add() method below walks down the list until it finds the appropriate position. Then, it splices in the new node and updates the start, prev, and curr pointers where applicable.
public void add(T x) {
Node newNode = new Node();
newNode.info = x;
// case: start is null; just assign start to the new node and return
if (start == null) {
start = newNode;
curr = start;
// prev is null, hence not formally assigned here
return;
}
// case: new node to be inserted comes before the current start;
// in this case, point the new node to start, update pointers, and return
if (x.compareTo(start.info) < 0) {
newNode.link = start;
start = newNode;
curr = start;
// again we leave prev undefined, as it is null
return;
}
// otherwise walk down the list until reaching either the end of the list
// or the first position whose element is greater than the node to be
// inserted; then insert the node and update the pointers
prev = start;
curr = start;
while (curr != null && x.compareTo(curr.info) >= 0) {
prev = curr;
curr = curr.link;
}
// splice in the new node and update the curr pointer (prev already correct)
newNode.link = prev.link;
prev.link = newNode;
curr = newNode;
}
Well the key to ensure its order is through your add() method.
To sort in ascending order:
1) Read current node's value.
2) Iterate through the nodes till you encounter a node with value >= with current.
3) Insert node at that position.
The above can be applied with binary search to get position for insertion.
To sort in descending order, just ensure current node's value is < target node's value.

How to set next value in a Circularly Linked List in Java?

This is what I have so far:
public void insert(int position, ValueNode value) {
if (position == 1) {
this.nextInRow = value;
}
ValueNode current = this.getFirst();
if (position > 1) {
current.setNext(current.next);
}
value.setNextInRow(current.getNext());
}
The headnode is being set properly with the first if statement. In this list we already know the position, so I'm thinking we don't need a while loop since we know where to put the new node.
I create a temp node called current to hold the next node pointer, but right now it sets the pointer to null. My problem is I don't know where to point the next node pointer to. Any help would be very much appreciated.
Distinguish making a node with value and setting next node operations.
Your data structure can be like this:
class Node {
int val;
Node next;
Node previous;
//setters and getters and constructors
}
1) For all new values should have a node
Node createNode(int val) {
Node newNode = new Node(val);
newNode.next = null;
newNode.previous = null;
return newNode;
}
2) Locate newNode starting from root or hold a current node set it next
currentNode.setNext(Node newNode);
//iterate the currenNode with newNode
currentNode = newNode;
...
// implement the setNext and mark current as previous for newNode
void setNextNode(Node newNode) {
this.next = newNode;
newNode.setPrevious(this);
}

Deleting a node that is in the middle of a linked list

I am trying to delete a node in the middle of two other nodes in a singly linked list.
public void deleteAfter(Node del){
del.next=del.next.next;
}
where it deletes the the node that is after the specified node,del.
I get a null pointer exception .I think the problem is after deletion the link with other nodes is broken.How can I mend it .Here's my full code :
public class Node{
public Object item;
public Node next;
public Node(){
item=null;
next=null;
}
public Node(Object x){
item=x;
next=null;
}
public void insertAfter(Node after,Object x){
Node newNode=new Node(x);
newNode.next=after.next;
after.next=newNode;
}
public void deleteAfter(Node del){//Deletes the node that is after the specified node
del.next=del.next.next;
}
public static void main (String args[]){
Node front=new Node(),p=new Node(),q=new Node();
p.item="green";
q.item="red";
p.next=q;
front=p;
front.deleteAfter(p);
front.insertAfter(p,"black");
front.insertAfter(q,"blue");
front.insertAfter(q.next,"orange");
front.deleteAfter(q);
System.out.println(front.item);
System.out.println(front.next.item);
System.out.println(front.next.next.item);
System.out.println(front.next.next.next.item);
}
}
First your list should remember last element or head.
public class YourList{
Node heaed;
public YourList(){
head = null;
}
public void insert(Node node){
if(last == null){
head = node;
}
}
public void deleteAfter(Node del){
if(del.next == head)){
head = del;
}
if(del.next == null){
//do nothing because there is nothing to delete
}
else{
del.next=del.next.next;
}
}
}
At:
p.next=q;
front=p;
front.deleteAfter(p);
front.insertAfter(p,"black");
You have created a two node linked list starting at p, and pointed front to it, then you shrank it down to a one node linked list, and bumped it back to two, consisting of { "green", "black" }. q is a singleton list node which you later manipulate.
When you print starting from front, since it only has two nodes, trying to obtain the item of the third node, which doesn't exist, causes your exception.
Your question started out by asking if there was something wrong with your deleteAfter(), and there is in that it won't correctly handle any correct list of nodes, only a list that actually has something after it. Passing in an empty list or a list with only one node in it will result in an exception.
You can first find the middle node using two pointer approach and then delete the node.
public Node findMiddleNode(Node node){
Node runner = node;
while(node!=null){
node = node.next;
if(node != null){
node = node.next;
runner = runner.next;
}
}
return runner;
}
public static boolean deleteNode(Node node){
if(node==null || node.next==null) return false;
Node next = node.next;
node.data = next.data;
node.next = next.next;
return true;
}
Solution which first calculates the size of the list and deletes the n/2 element without using two pointers.
For example, if given linked list is 1->2->3->4->5 then linked list should be modified to 1->2->4->5. If there are even nodes, then there would be two middle nodes, the second middle element gets deleted. For example, if given linked list is 1->2->3->4->5->6 then it should be modified to 1->2->3->5->6.
public void deleteMiddle() {
if (head == null) {
System.out.println("List is emplty");
return;
} else if (head.next == null) {
head = null;
return;
} else {
int count = 0;
int nodeDeleteIndex = 0;
Node node = this.head;
Node temp = this.head;
// To calculate the list size
while (node != null) {
count++;
node = node.next;
}
// getting the n/2 index of the node which needs to be deleted
nodeDeleteIndex = (count / 2);
for (int i = 0; i < nodeDeleteIndex - 1; i++) {
temp = temp.next;
}
temp.next = temp.next.next;
}
}

Invert linear linked list

a linear linked list is a set of nodes. This is how a node is defined (to keep it easy we do not distinguish between node an list):
class Node{
Object data;
Node link;
public Node(Object pData, Node pLink){
this.data = pData;
this.link = pLink;
}
public String toString(){
if(this.link != null){
return this.data.toString() + this.link.toString();
}else{
return this.data.toString() ;
}
}
public void inc(){
this.data = new Integer((Integer)this.data + 1);
}
public void lappend(Node list){
Node child = this.link;
while(child != null){
child = child.link;
}
child.link = list;
}
public Node copy(){
if(this.link != null){
return new Node(new Integer((Integer)this.data), this.link.copy());
}else{
return new Node(new Integer((Integer)this.data), null);
}
}
public Node invert(){
Node child = this.link;
while(child != null){
child = child.link;
}
child.link = this;....
}
}
I am able to make a deep copy of the list. Now I want to invert the list so that the first node is the last and the last the first. The inverted list has to be a deep copy.
I started developing the invert function but I am not sure. Any Ideas?
Update: Maybe there is a recursive way since the linear linked list is a recursive data structure.
I would take the first element, iterate through the list until I get to a node that has no child and append the first element, I would repeat this for the second, third....
I sometimes ask this question in interviews...
I would not recommend using a recursive solution, or using a stack to solve this. There's no point in allocating O(n) memory for such a task.
Here's a simple O(1) solution (I didn't run it right now, so I apologize if it needs some correction).
Node reverse (Node current) {
Node prev = null;
while (current != null) {
Node nextNode = current.next;
current.next = prev;
prev = current;
current = nextNode;
}
return prev;
}
BTW: Does the lappend method works? It seems like it would always throw a NullReferenceException.
There's a great recursive solution to this problem based on the following observations:
The reverse of the empty list is the empty list.
The reverse of a singleton list is itself.
The reverse of a list of a node N followed by a list L is the reverse of the list L followed by the node N.
You can therefore implement the reverse function using pseudocode along these lines:
void reverseList(Node node) {
if (node == null) return; // Reverse of empty list is itself.
if (node.next == null) return; // Reverse of singleton list is itself.
reverseList(node.next); // Reverse the rest of the list
appendNodeToList(node, node.next); // Append the new value.
}
A naive implementation of this algorithm runs in O(n2), since each reversal requires an append, which requires an O(n) scan over the rest of the list. However, you can actually get this working in O(n) using a clever observation. Suppose that you have a linked list that looks like this:
n1 --> n2 --> [rest of the list]
If you reverse the list beginning at n2, then you end up with this setup:
n1 [reverse of rest of the list] --> n2
| ^
+------------------------------------------+
So you can append n1 to the reverse of the rest of the list by setting n1.next.next = n1, which changes n2, the new end of the reverse list, to point at n1:
[reverse of the rest of the list] --> n2 --> n1
And you're golden! Again more pseudocode:
void reverseList(Node node) {
if (node == null) return; // Reverse of empty list is itself.
if (node.next == null) return; // Reverse of singleton list is itself.
reverseList(node.next); // Reverse the rest of the list
node.next.next = node; // Append the new value.
}
EDIT: As Ran pointed out, this uses the call stack for its storage space and thus risks a stack overflow. If you want to use an explicit stack instead, you can do so like this:
void reverseList(Node node) {
/* Make a stack of the reverse of the nodes. */
Stack<Node> s = new Stack<Node>();
for (Node curr = node; node != null; node = node.next)
s.push(curr);
/* Start unwinding it. */
Node curr = null;
while (!s.empty()) {
Node top = s.pop();
/* If there is no node in the list yet, set it to the current node. */
if (curr == null)
curr = top;
/* Otherwise, have the current node point to this next node. */
else
curr.next = top;
/* Update the current pointer to be this new node. */
curr = top;
}
}
I believe that this similarly inverts the linked list elements.
I would treat the current list as a stack (here's my pseudo code):
Node x = copyOf(list.head);
x.link = null;
foreach(node in list){
Node temp = copyOf(list.head);
temp.link = x;
x = temp;
}
At the end x will be the head of the reversed list.
I more fammiliar whit C, but still let me try. ( I just do not sure if this runs in Java, but it should)
node n = (well first one)
node prev = NULL;
node t;
while(n != NULL)
{
t = n.next;
n.next = prev;
prev = n;
n = t;
}
Reversing a single-linked list is sort of a classic question. It's answered here as well (and well answered), it does not requires recursion nor extra memory, besides a register (or 2) for reference keeping.
However to the OP, I guess it's a school project/homework and some piece of advice, if you ever get to use single linked list for some real data storage, consider using a tail node as well. (as of now single linked lists are almost extinct, HashMap buckets comes to mind, though).
Unless you have to check all the nodes for some condition during 'add', tail is quite an improvement. Below there is some code that features the reverse method and a tail node.
package t1;
public class SList {
Node head = new Node();
Node tail = head;
private static class Node{
Node link;
int data;
}
void add(int i){
Node n = new Node();
n.data = i;
tail = tail.link =n;
}
void reverse(){
tail = head;
head = reverse(head);
tail.link = null;//former head still links back, so clear it
}
private static Node reverse(Node head){
for (Node n=head.link, link; n!=null; n=link){//essentially replace head w/ the next and relink
link = n.link;
n.link = head;
head = n;
}
return head;
}
void print(){
for (Node n=head; n!=null;n=n.link){
System.out.println(n.data);
}
}
public static void main(String[] args) {
SList l = new SList();
l.add(1);l.add(2);l.add(3);l.add(4);
l.print();
System.out.println("==");
l.reverse();
l.print();
}
}
I was wondering something like that(I didnt test it, so):
invert(){
m(firstNode, null);
}
m(Node v, Node bef){
if(v.link != null)
m(v.link,v);
else
v.link=bef;
}
Without much testing,
Node head = this;
Node middle = null;
Node trail = null;
while (head != null) {
trail = middle;
middle = head;
head = head.link;
middle.link = trail;
}
head = middle;
return head;
public ListNode Reverse(ListNode list)
{
if (list == null) return null;
if (list.next == null) return list;
ListNode secondElem = list.next;
ListNode reverseRest = Reverse(secondElem);
secondElem.Next = list;
return reverseRest;
}
Hope this helps.

Categories