can someone please tell me if I am correct? I am studying for a midterm.
x is a variable pointing to a linked-list node and not the last node on the
list. t points to a new node that is not in the list.
x.next = t;
t.next = x.next;
I believe when it comes time to update t.next, x.next is no longer the original node following x, but is instead t itself. So it create a cycle in the list
t = x.next
x = t;
I believe this does nothing to the list.
Thank you in advance!!
You can also do it threadsafe like this:
t.next = x.next; // let t and x point to the SAME next.
x.next = t; // change the x.next to t(who has the old next)
In this case store node in temp variable. It won't create the cycle.
Object temp = x.next;
x.next = t;
t.next = temp;
First you have list like this..
X--->Y----->Z-->
You want to insert a node t after X
Right now t is
t---->null
Step 1- Now we have temp pointing to X's next
x---->y----->z----->
^
|
temp--
Step 2- Now x's next is pointing to t
x----->t---->
now main list is like this
temp---->y---->z---->
Step 3- Now t's next is pointing to temp which is only next pointer
temp---->y--->z---->
^
|
----------
|
x---->t---
So resulting list is
x--->t---->y---->z----->
You already have object x. This probably the current last element of the linked list. Now, you create a new object T and link it as the element after X
X // Lets assume X.next == NULL. So linked list looks like this X -> Null
X.next = T // Now X.next == T and T.Next == NULL, So linked list looks like this X -> T -> Null.
T.next = X.next // Now T.next == T. So linked list is X -> T <->T
This way, when you reach the end of the linked list, it will always return the last element instead of returning NULL.
If you are writing a simple algorithm for this, first you have to create an element and then point its next variable to it self.<First_element>.next = <First_element>. So the logic will work for all the instances.
Here is a simple experiment.
class Node{
Node next = null;
int id =-1;
}
public class LinkedList{
public static void main (String args[]){
Node x = new Node();
x.id = 0;
x.next = x;
// Now add a new element
Node t = new Node();
t.id =1;
x.next = t;
t.next = x.next; // Now we have a linked list of 2 elements
Node mynode = x;//First element of linked list
for(int i =0; i < 3; i++){
System.out.println(mynode.id);
mynode = mynode.next;
}
}
}
Output:
0
1
1
Related
I'm trying to add a node in a circular list in Java. The problem is that my list has only a head (without a tail). Here is my code:
import java.io.PrintStream;
import java.util.EmptyStackException;
public class CircularList {
private Node head = null;
private class Node {
public Node(String payload, Node prev, Node next) {
super();
this.payload = payload;
this.prev = prev;
this.next = next;
}
private Node prev;
private Node next;
String payload = "";
}
public void push(String payload) {
Node n = new Node(payload, null, null);
if (isEmpty()) {
head = n;
n.next = n;
} else {
n.prev = head;
n.next = head;
}
}
Lets take some nodes.
< H - < A - < B -
This describes the connections of the nodes. A.next == H and A.prev == B.
H and B are special cases, where H is the head and B is the tail. Since the list is circular. Then H.next == B and B.prev == H.
When we push a node.
< N - < H - < A - < B -
Then we can see all of the assignments that need to change.
H = head;
B = H.next; // get the tail since you only have the head.
H.next = N;
N.prev = H;
N.next = B;
B.prev = N;
head = N;
You're almost there. When the list is empty, that part works fine. But when the list is not empty, think through what needs to happen, which is 4 things:
The 'head's previous node needs to become the new node.
The new node's 'next' needs to point at head.
The new node's 'previous' needs to point at what used to be head.prev.
What used to be head.prev's next pointer needs to point at the new node.
You'll need some temp variables to take care of all of that.
I need some help understanding how a method works.
I have a basic Node class defined like this:
class Node {
Node next = null;
int data;
public Node(int d){
data = d;
}
}
Now I'm looking at how this deleteDuplicates method is working. I understand that we are passing through each node iteratively and storing its value in a set. If the value is already in the set, I believe we are setting the previous node's next pointer to skip the current node. Here's the method:
public static Node deleteDuplicates(Node head){
Node n = head;
HashSet<Integer> set = new HashSet<Integer>();
Node previous = null;
while(n != null) {
if (set.contains(n.data)){
// skip this node
previous.next = n.next;
}
else {
set.add(n.data);
previous = n;
}
n = n.next;
}
return head;
}
I'm confused about the variables previous and n. When we set previous = n;, isn't that making them reference the same object? If they reference the same object, one change you make to n will be the same in previous. So how does the line previous.next = n.next; work?
Thanks!
read these 2 lines together,
previous = n;
n = n.next;
So, once a node is processed, the pointers for previous and n are moved forward. n is next node after previous, thus previous is set to n, and n is moved to its next node, which is n.next
For the deletion part, hope the diagram below helps
While solving the problem that reverse first K elements of linked list i have written the below recursive code but the last iteration executing twice i.e for k=1, function call reverseNode() happening twice. Can any body why it happening like that. Please correct me if i did any thing wrong in it.
Example :
If input is
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8
and k = 4 then output is
4 -> 3 -> 2 -> 1 -> 5 -> 6 -> 7 -> 8
public void reverseListRecursion(int k) {
this.reverseNode(null, headNode,k);
}
public void reverseNode(Node node, Node nextNode,int k) {
while (k > 0) {
k = k-1;
this.reverseNode(node, nextNode.next,k);
}
if (k == 0) {
this.kNode = nextNode;
this.kNode.next = null;
}
if (node == null) {
nextNode.next = this.kNode;
} else {
nextNode.next = node;
}
}
Working code for my logic it is working expected. but when i try to use variable "k" in "if" condition instead of "presentCounter" then it is going wrong. Can any body tell me the reason.
public void reverseListRecursion(int count) {
this.reverseNode(null, headNode, count);
System.out.println("\n");
this.display(this.headNode);
}
/*
* Condition K <= Length of linked list.
*/
public void reverseNode(Node node, Node nextNode, int k) {
int presentCounter = k;
if (k > 1) {
k = k - 1;
this.reverseNode(nextNode, nextNode.next, k);
}
if (presentCounter == 1) {
this.kNode = nextNode.next; // Saving K's Next Node
this.headNode = nextNode; // Setting K node as head node
}
if (node == null) {
nextNode.next = this.kNode;
} else
nextNode.next = node;
}
Your recursion should be
if (k > 0) { // and not while
k = k-1;
this.reverseNode(node, nextNode.next,k);
}
...
There are several issues with this code you provided in your question:
public void reverseListRecursion(int k) {
this.reverseNode(null, headNode,k);
}
public void reverseNode(Node node, Node nextNode,int k) {
while (k > 0) {
k = k-1;
this.reverseNode(node, nextNode.next,k);
}
if (k == 0) {
this.kNode = nextNode;
this.kNode.next = null;
}
if (node == null) {
nextNode.next = this.kNode;
} else {
nextNode.next = node;
}
}
The wile loop will make the number of recursive calls grow to k!. Maybe this was your intention, but it certainly would not make an efficient algorithm. The job can be done by moving k-1 nodes, so making k! calls is not so efficient.
The first argument (node) never changes: the recursive call just passes the same argument, and so the value you pass in the initial call (null) is what this argument will be in every call. The outcome of the last if condition will therefore always be the same. This doesn't look right.
The first if condition will always be true, because it is opposite to the while condition that precedes it. So there should be no need to make the test for k == 0.
The code within the first if block makes this.kNode a synonym for nextNode and then its next property is set to null. There should be no reason at all to set any next property to null. If anything, it will break the linked list.
In the second if block the next property of nextNode is set to ... nextNode (see previous point, which shows that this.kNode was made synonymous for nextNode). So now you have a self-referencing node, which really is something you'd never want to have. This code makes the first k+1 nodes self-referencing, thereby effectively detaching them from the original linked list.
The initial call is made with headNode as second argument. This variable is apparently a private member of the class you are in. However, after execution the reversal, headNode will still reference the node it referred to before the call. The name suggests it should point to the first node in the list, but since the reversal will move another node at the front, headNode will point to the wrong node after completion. There is no other variable or property you have that will point to the first node in the list after the reversal. this.kNode could have been it, but the statements this.kNode.next = null and nextNode.next = this.kNode are not things you would do with the first node of a list.
There are too many issues with this code to get a clear view on what you actually tried to do.
I would suggest to go for this algorithm, explained by example:
list = 1 2 3 4 5 6 7 8
k = 4
Move the node that follows the original first node to the head of the list
list = 2 1 3 4 5 6 7 8
k = 3
Move the node that follows the original first node to the head of the list
list = 3 2 1 4 5 6 7 8
k = 2
Move the node that follows the original first node to the head of the list
list = 4 3 2 1 5 6 7 8
k = 1
As k = 1 no more moves have to be made.
This is how your code would look:
public void reverseListRecursion(int k) {
// The reversal returns the node that took the first position
this.headNode = this.reverseNode(this.headNode, k, this.headNode);
};
public Node reverseNode(Node origFirstNode, int k, Node currFirstNode) {
// If 1 element needs to be reversed, there is nothing to do:
if (k <= 1) return currFirstNode;
// Move the node after the original first node before the current first node
Node movingNode = origFirstNode.next;
origFirstNode.next = movingNode.next;
movingNode.next = currFirstNode;
// The moved node is now the current first node. Repeat:
return this.reverseNode(origFirstNode, k-1, movingNode);
};
The nice thing about this solution is that the reverseNode method does not need to reference this.headNode, and so it can be used to reverse elements in the middle of the list as well. You could add this method which takes a node as second argument:
public void reverseListRecursionAfter(int k, Node afterNode) {
afterNode.next = this.reverseNode(afterNode.next, k, afterNode.next);
};
This will reverse the nodes following the given node.
Here is a live snippet, with the same code translated to JavaScript (just for demo):
// Node class
function Node(val, next) {
this.val = val;
this.next = next;
this.toString = function (cascade) {
if (!cascade || this.next === null) return '(' + this.val + ')';
if (this.next === this) return '(' + this.val + ')-loop';
return '(' + this.val + ')->' + this.next.toString(true);
}
}
// List class
function List() {
this.headNode = null;
this.reverseListRecursion = function(k) {
// The reversal returns the node that took the first position
this.headNode = this.reverseNode(this.headNode, k, this.headNode);
};
this.reverseNode = function(origFirstNode, k, currFirstNode) {
// If 1 element needs to be reversed, there is nothing to do:
if (k <= 1) return currFirstNode;
// Move the node after the original first node before the current first node
var movingNode = origFirstNode.next;
origFirstNode.next = movingNode.next;
movingNode.next = currFirstNode;
// The moved node is now the current first node. Repeat:
return this.reverseNode(origFirstNode, k-1, movingNode);
};
this.insert = function (arr) {
for (var i = arr.length - 1; i >= 0; i--) {
this.headNode = new Node(arr[i], this.headNode);
}
}
this.toString = function () {
return '{' + this.headNode.toString(true) + '}';
}
}
var output = [];
// Sample data
var list = new List();
list.insert([1, 2, 3, 4, 5, 6, 7, 8]);
output.push('before: ' + list);
// Make the reversal call
list.reverseListRecursion(4);
output.push('after: ' + list);
// Show result in snippet
document.write(output.join('<br>'));
I'm having what I'm sure is a basic logic error but I can't seem to fix it. I'm sorting a GenericSimpleArrayList before creating a tree using both the unsorted (postorder) and sorted (inorder) lists. When I sort one of the lists it sorts them both? I'm not sure why.
public static <AnyType extends Comparable<? super AnyType>> BinaryNode<AnyType>constructBST ( GenericSimpleArrayList<AnyType> postorder ){
GenericSimpleArrayList <AnyType> g = postorder;
quicksort(postorder, new SortFunctor()); //this is where i sort the list.
GenericSimpleArrayList <AnyType> inorder = postorder;
return constructTree(inorder, g);
}
Can anyone help me fix this? Why does it sort both g and postorder when I only sort postorder? Thanks.
Edit: Added constructTree.
public static <AnyType> BinaryNode<AnyType> constructTree(GenericSimpleArrayList<AnyType> inorder, GenericSimpleArrayList<AnyType> postorder) {
int nodes = postorder.size();
AnyType root = postorder.get(nodes-1);
BinaryNode<AnyType> left = null;
BinaryNode<AnyType> right = null;
if (nodes > 1) {
int rootPos = 0;
for (int loop = 0; loop <= nodes-1; loop++) {
if (inorder.get(loop).equals(root)) {
rootPos = loop;
//System.out.println(loop);
} else {
//System.out.println("Not found at pos: " + loop);
}
}
if (rootPos != 0) {
GenericSimpleArrayList <AnyType> leftInorder = new GenericSimpleArrayList();//(AnyType) new Object[rootPos];
GenericSimpleArrayList <AnyType> leftPostorder = new GenericSimpleArrayList();//(AnyType[]) new Object[rootPos];
for (int loop = 0; loop < rootPos; loop++) {
leftInorder.add(inorder.get(loop));
leftPostorder.add(postorder.get(loop));
}
left = constructTree(leftInorder, leftPostorder );
}
if (rootPos < nodes-1){
GenericSimpleArrayList <AnyType> rightInorder = new GenericSimpleArrayList();//(AnyType[]) new Object[nodes - rootPos - 1];
GenericSimpleArrayList <AnyType> rightPostorder = new GenericSimpleArrayList();//(AnyType[]) new Object[rightInorder.length];
for (int loop = 0; loop < nodes-rootPos-1; loop++){
rightInorder.add(inorder.get(rootPos + loop + 1));
rightPostorder.add(postorder.get(rootPos + loop));
}
right = constructTree(rightInorder, rightPostorder);
}
}
return new BinaryNode<AnyType>(root, left, right);
}
Why does it sort both g and postorder when I only sort postorder?
GenericSimpleArrayList <AnyType> g = postorder;
postorder is a reference to an object. When you copy this reference you now have two references to an object. However there is still only one object.
I don't know the API to your custom ArrayList but I assume you can do
GenericSimpleArrayList<AnyType> g = new GenericSimpleArrayList<AnyType>(postorder);
or
GenericSimpleArrayList<AnyType> g = new GenericSimpleArrayList<AnyType>();
for(AnyType at: postorder)
g.add(at);
Most likely your sorting utility sorts the collection in place. This is very common for sort functions to alter the original list.
If you want to preserve both the original order and sort the list, I suggest first taking a copy of the list.
An alternetive is to use a different structures like a TreeMap to record the String in sorted order and the index of the original position.
GenericSimpleArrayList <AnyType> g = postorder;
GenericSimpleArrayList <AnyType> inorder = postorder;
In these two statements, all the three variable will be referring to the same reference hold by postorder initially. Because you are doing reference assignment and update in one object state will reflect into all the reference variable.
constructTree(inorder, g);
So when you make the above call then you are passing the same same reference.
In this line:
GenericSimpleArrayList <AnyType> g = postorder;
you only define a new name g for the same object. If you want g to be a different List, you need to create it newly (that is really call the constructor) and copy postorder's contents into it.
Given two double linked lists I'm supposed to change, not just the elements, but the nodes of one of the lists so that the sum in the same positions equals a certain number.
public void repair(int num){
Node list1 = head1;
Node right = head2;
for(int i = 0; i<size; i++){
int element = num - list1.element;
Node p = right.previous;
Node s = right.next;
right = new Node(element, null, null);
p.next = right;
right.previous = p;
right.next = s;
s.previous = right;
list1 = list1.next;
right = right.next;
}
}
size = size of both list which is the same.
I've tried a lot of things but it always gives me nullpointerexception on p.next = right and s.previous = right;
I don't understand why it gives me this error. Can someone explain and show me a way of solving this?
It means p is null
Node p = right.previous;
Must be returning null
Seeing as right is defined as head2, you will have to look into head 2 and work out why head2.previous is null. I guess it is the beginning of the list or something.
You need to put null checks in so you only run operations on next / previous nodes when they are not null.