I'm familiar with the 'this' keyword used in java, it is used to reference the current object. The following piece of code shows how a node of a LinkedList is created:
class Node {
Node next = null;
int data;
public Node(int d) {
data = d;
}
void appendToTail(int d) {
Node end = new Node(d);
Node n = this;
while (n.next != null) {
n = n.next;
}
n.next = end;
}
}
But here I'm not sure what the following line in the above code states:
Node n = this;
I'm pretty sure that 'this' here is referenced to the current object, but is this object head, tail or any other node in the LinkedList? Not sure if my question makes perfect sense, but any help is greatly appreciated.
I assume the appendToTail(int d) method appends the newly created node to the end of the list regardless of which Node its called from.
What happens is that one must find the end of the list in order to append the new Node to the end of it. Since we know that the node it is called from is in the list, it's an ideal starting point. Hence we choose the starting point as "this" node. But, this node is not necessarily the end of the list (in fact, it can be anywhere in the list), so we store it in a temporary variable Node n = this and continue changing our temporary variable until its the last node in the list, to which the new node can be added.
It's equivalent to starting from a random point (this) in a list and moving from that point to the end, wherever that is.
Hope this answered your question.
I'm pretty sure that 'this' here is referenced to the current object
Yup.
but is this object head, tail or any other node in the LinkedList?
That depends where the method was called from or if the list contains this Node at all.
All the method does is assign a temporary reference to the current Node so it can be iterated over. You can't say which Node it is without more information.
From comments - If you call appendToTail() on the head, this will be the head. If you call it on the tail, this will be the tail. If you call it on a middle node, this will be that middle node.
Related
I am working on a problem: create a stack using a linked chain that places the new entry (top of stack) at the end of the chain, not the beginning. Part of the solution involves maintaining a reference to the first and last nodes and the next to last node. Also, I cannot traverse the chain. I cannot think of a solution because I cannot think of a way to update the reference to the next to last node when the top entry is popped off the stack?
(This is a textbook question. The beginning of the chain contains a reference to the next node. The end of the chain's reference to the next node is null)
Beginning and end are abstract terms. Just initialize a node to contain the first element. Something like the following:
Node tail = null;
..
..
Then to add a new node.
public void push(T val) {
Node = new Node(val);
Node.next = tail;
tail = node;
}
You're adding it at the tail and then the new node becomes the tail. Then when you iterate thru it you simply start at the tail and move towards the head using the next reference.
To pop the stack.
public T pop() {
if (tail != null) {
object = tail.object;
tail = tail.next;
}
return null;
}
You will need to create a generic class Node. And you may want to have an isEmpty() method.
i wanna swap 2 nodes in java here is my node class
public class Node {
int freq;
Node left,right,parent;
}
i wanna swap 2 Nodes in my tree
public void swap(Node a, Node b){
Node temp;
temp.freq=a.freq;
temp.parent=a.parent;
temp.left=a.left;
temp.right= a.right;
a.freq=b.freq;
a.left=b.left;
a.right=b.right;
a.parent=b.parent;
b.freq=temp.freq;
b.left=temp.left;
b.right=temp.right;
b.parent=temp.parent;
}
but i found that parent of both nodes becomes b.parent
any hint ????
Looking at your object, Node temp doesn't point to anything besides null. I don't know why your compiler isn't catching this error because using a dot call on a null object will throw a nullpointerexception(e.g. temp.freq; it will have nothing to point to and no internal variables at this point). Make sure that temp points to a new node and try going from there.
I' studying linked lists. I'm practicing problems from this book : Cracking the coding interview. I'm stuck, I can't understand how the author is trying to implement the following code, its supposed to delete a node....
class Node {
Node next = null;
int data;
public Node (int d) {
data = d;
}
Node deleteNode(Node head, int d) {
Node n = head;
if (n.data == d) {
return head.next;
}
while (n.next != null) {
if (n.next.data == d) {
n.next = n.next.next;
return head;
}
n = n.next;
}
return head;
}
I've 3 questions...
Question 1 -
What are we going to pass as the argument for the function deleteNode? What purpose does Node head serve? and what purpose does int d serve? Is the node head the node we want to delete? Or is it our head node? I mean, we are supposed to use the method as following right?
"Name of node".deleteNode("Node name", "integer value");
"Name of node" being the node we want to delete...Isn't that right?
Question 2 - Its clear in the code that the function deleteNode uses only data to confirm the identity of the node we want to delete. E.g. if(n.data ==d). Is that normal practice? I mean what if I have 2 different nodes containing the same integer as the data value? Shouldn't we use the name of the node to specify which node we want to delete?
Question 3 - function deleteNode returns a node. Why is that? In order to delete a node, we only gotta do 3 things...First, unlink the pointer of the node we want to delete. Second, put the pointer of the previous node, to the node where the pointer of the node we wanted to delete was originally pointing. Third, delete the node now that its not linked to the list. I don't see what purpose does return type node serves here...
Question 1 : All along your post, you keep talking about the "name" of the nodes, but the nodes have no name. They have an int value and a successor, that's all. In this deleteNode method, the first argument is the head of the linked list from which you want to remove the first occurrence of the value d.
Question 2 : As I said, the nodes have no name and are identified by their value. As soon as an occurrence of the wanted value is found, the corresponding node is deleted no matter how many occurrences of the same value are in the linked list.
Question 3 : the method returns the head of the list, so that you can chain multiple calls like this
myList.deleteNode(head,3).deleteNode(head,5).addNode(head,10)
If the method had a void return type, you should do
myList.deleteNode(head,3);
myList.deleteNode(head,5);
myList.addNode(head,10);
I was just playing around with a binary tree and I was curious as to why the first implementation worked but the second didn't. What am I overlooking? I think it's trivial but I'm still missing it.
1:
//just a wrapper around the insertTree method.
public void insertKey(int key){
if(root==null) //a private 'Node' variable.
root = new Node(key);
else
insertTree(key, root);
}
//recursive insert - working
private void insertTree(int key, Node node)
{
if(key <= node.getKey())
{
if(node.left!=null)
insertTree(key, node.left);
else
node.left = new Node(key); //explicitly setting left child
}
else
{
if(node.right!=null)
insertTree(key, node.right);
else
node.right = new Node(key); //explicitly setting right child
}
}
The variant that is not working:
2:
private void insertTree(int key, Node node)
{ //if node is null, create a new node. Can be either node.left or node.right
if(node==null)
{
node = new Node(key);
return;
}
else
if(key <= node.getKey())
insertTree(key, node.left);
else
insertTree(key, node.right);
}
Node is just a simple class with public left, right members and a single int key data member. Nothing fancy. So #1 works just fine and the inorder traversal produces a sorted output. Now, #2 doesn't seem to work. The root is the only one that is initialized and its left/right children continue to be null. So if I do pass node.left as a parameter, why doesn't the recursive method call assign a new node to it? What am I missing here? Java is pass by reference (i.e. value of reference) so I'm guessing this should work, but maybe I'm missing something noob-ish over here.
The reason it doesn't work is because the node variable in the last recursive call to insertTree does not actually refer to the same memory location as node.left in the call that preceded it. Calling a function(/method) effectively creates new storage locations for all its parameters on the stack, and copies the parameter values there.
Therefore, insertTree in your second variant simply creates a new Node and assigns it to the local variable node in that function. That assignment affects no other memory location. Then it returns, and the new Node is lost forever.
You state that "Java is pass by reference", but that's not true. Java passes references by-value.
You should not be using recursion to add elements to a binary tree. Recursions involve implicit stacks which are expensive. You should simply iterate to find the correct location for adding the node. Plus, when you use iterating, you don't need two methods to do the work -- one is enough. Look at the following very simple code: http://www.geekviewpoint.com/java/bst/add
I am solving the problem in the interview question about LinkedList.
question is...
Write code to remove duplicates from an unsorted linked list
FOLLOW UP
How would you solve this problem if a temporary buffer is not allowed?
I was reading the solution and I dont understand three parts in the solution.
First,
public static void deletedup(LinkedListNode n)
{
Hashtable table = new Hashtable();
LinkedListNode prev = null;
while(n != null)
{
if(table.containsKey(n.data))
prev.next = n.next; //<--
else
table.put(n.data, true);
prev = n;//<--
}
n = n.next;
}
First-1 question.
In the solution, if table contains the duplicated keyword. they have move to next node.
I was thinking the we just need to to n = n.next. However, solution was doing prev.next= n.next;. However, we don't really sure prev in the code. Why do we have to use prev ?
Moreover,
after putting unique keyword in the table solution assign n to prev (prev = n;). Why do we have to do it ?
Second,
public static void deletedup(LinkedListNode head)
{
LinkedListNode pre = head;
LinkedListNode cur = pre.next;
while(cur != null){
LinkedListNode runner =head;
while(runner != current)
{
if(runner.data == cur.data)
{
LinkedListNode tmp = current.next;
pre.next = tmp;//<---
current = tmp;//<--
break;
}
[...]
}
[...]
}
}
Second question , from the second solution , it program find the duplicated keywords, we have to remove it. Therefore, they declare tmp node to remove to remove duplicated keyowrds.
However, I don't really understand the reason to do " pre.next = tmp and cur = tmp".
I am guessing thet "cur = tmp" will update the current to next node. However, I am not really sure about the reasons..
Third, for the Big o part . I am assuming that first solution will be O(n) and second solution will be O(n^2). Is it right ?
thanks
First Question:
n is a reference to a node. It is a local reference that is only valid in this function.
Say we are accessing the linked list in the future.
The way a node is discovered is by the reference 'r' located in the previous node. We need to change that reference. If we change n, it will not make any difference to 'r'.
If you're from the C/C++ world, think of n as being like a unique pointer to a node. Will changing the value of this pointer change the value of 'r'? I think not.
Second Question:
I think your doubt here might be related to assignments. WHen we say 'current.next', we are referring to the 'next' variable in object 'current'. We are not saying, 'advance current to the next node'. That is why 'current.next' will not really change any variables. When we say 'current = current.next', we are saying, okay, i want to change the node that 'current' is pointing to, and i want to change it to 'current.next', the next node.
Also, I believe you are right about the complexity.
first question:
n = n.next has no no affect on the list itself - it will only advance the value of the variable n to its following element, without touching the actual elements in the list.
Doing prev.next= n.next is updating the field next in the object which prev references to - and putting the value of n.next [which is a reference to an object] there.
second question:
Same issue, curr = temp will have no affect on the list, it will only modify the value of the variable.