i was wondering if anyone could help me with this question. i believe i understand the code and logic for the most part. i can trace code and it makes sense, but one thing i don't get is....how does the LinkedListNode previous actually change the LinkedListNode n that is passed in?
it seems to me that the function loops through n, and if the element is not yet found puts it into a hashtable. but when it is found again, it uses this newly created LinkedListNode previous to skip over the duplicate and link to the following element, which is n.next.
How does that actually disconnect LinkedListNode n? It seems like previous would be the LinkedListNode that has no duplicates, but since nothing gets returned in this function, n must be the one that changes. I guess I'm not seeing how n actually gets changed.
Clear and thorough help would be much appreciated. Thank you = )
public static void deleteDups(LinkedListNode n){
Hashtable table = new Hashtable();
LinkedListNode previous = null;
while(n != null){
if(table.containsKey(n.data))
previous.next = n.next
else{
table.put(n.data, true);
previous = n;
}
n = n.next;
}
}
doesn't the line...
LinkedListNode previous = null;
create a new LinkedListNode?
so this is my logic of how i'm doing it...
lets say the argument, n, gets passed in as
5 -> 6 -> 5 -> 7
when the code first runs, previous is null. it goes into the else statement, and previous is now 5? and then the line n = n.next makes n 6? now the hashtable has 5, and it loops again and goes into the else. prev is now 6 and the hastable has 6. then n becomes 5. it loops again but this time it goes into the if, and prev is now 7. and n will become 7. i see that prev skipped over 5, but ...how is prev unlinking n? it seems like prev is the LinkedListNode that contains no duplicates
how does the LinkedListNode previous actually change the
LinkedListNode n that is passed in?
Look at the line
n = n.next;
This line causes the passed node n to change - effectively moving it one node forward with each iteration.
it uses this newly created LinkedListNode previous to skip over the duplicate and link to the following element
No, no node is newly created here. The node previous always points to a node in the existing LinkedList of which the passed node n is one of the nodes. ( may be the starting node ). What makes you think it is newly created ?
It looks like you are confused in your understanding of how nodes and references ( and so a LinkedList as a whole ) works in Java. Because all modifications occur on the Node's data , and not the reference itself , ( ugh.. thats not entirely correct ), the original LinkedList passed to the method does get modified indeed after the method returns. You will need to analyse the LinkedList structure and workings in details to understand how this works. I suggest first get clarity about what pass by value and pass by references are in Java.
edit :
Your analysis of the run is correct , however your confusion still remains because you are not conceptually clear on certain things.
Towards the end of your analysis , you ask "..how is prev unlinking n? it seems like prev is the LinkedListNode that contains no duplicates "
This is a mess - first , you need to differentiate between a LinkedListNode and a LinkedList itself. prev and n are two instances of LinkedListNode, not LinkedList itself. In your example , the LinkedList is unnamed ( we dont have a name to refer to it ). This is the original list - there is no other list.
Second , in your illustration , the numbers you show are only one part of the node , called the node data. The other part, that you have missed out, is the next LinkedListNode reference that is implicit in every node. The link that you draw -> is actually the next reference in each node.When you say that prev skips 5 , what actually happens is that the next of node with data 6 is made to point to node with data 7.
At start :
5|next -> 6|next -> 5|next -> 7|next->NULL
After 5 is skipped :
5|next -> 6|next -> 7|next->NULL
As you see , the linkedlist is changed ! It does not matter if it was changed using prev or n, the change remains in the list.
if(table.containsKey(n.data))
previous.next = n.next
Is the section which does the deletion. It assigns the reference of the prior node's next field to the node after the current node, in effect unlinking the current node.
Related
This is the question I'm working on: Print reverse of a Linked List without actually reversing.
Here is a link to the answer provided by GeeksforGeeks:
I've been looking at what happens step by step with the IntelliJ debug tool but still don't understand how it works.I see that we iterate through the list until the very end and somehow the function starts going backward after we pass the last node? How?Could someone explain this to me please?
void printReverse(Node head)
{
if (head == null) return;
// print list of head node
printReverse(head.next);
// After everything else is printed
System.out.print(head.data+" ");
}
In order to understand this, you need to understand the concept of LIFO (Last In, First Out).
This is the basic concept for a data structured called the stack, which is of great relevance in our case, because the memory section where function calls are being stored is called the stack, because it operates as a stack.
Let's see your method:
void printReverse(Node head)
{
if (head == null) return;
// print list of head node
printReverse(head.next);
// After everything else is printed
System.out.print(head.data+" ");
}
Initially this is called by passing the very first node of your linked list. By the way, let's imagine that your linked list has n elements, of the form of
l(1) -> l(2) -> ... -> l(n) -> null
The i'th call to printReverse checks whether head is null, which, if true, then we have reached the end of the list.
Now, here's what happens:
We reach l(1), which calls printReverse for l(2) and waits for it to complete before printing the value of l(1). The call for printReverse, on l(2), on its turn calls printReverse on l(3) and waits for it to complete, before completing and so on. Once the stack is fully built and we reach the null, then the n+1'th function call returns without a print. Then, the n'th call finishes the printReverse line and prints and so on.
For illustration, let's consider the following list:
1 -> 2 -> 3 -> null
This is what happens:
calling printReverse for the first item
is the node (the first one) null? No
calling printReverse for the second item
is the node (the second one) null? No
calling printReverse for the third item
is the node (the third one) null? No
calling printReverse for the fourth (nonexistent) item
is the node (the null after the last element) null? Yes, do nothing
printing 3
printing 2
printing 1
As you can see, each function call is a level deeper than the former function call and the former function call waits for the functions it called to evaluate. Since it prints after its function calls, this means that when the method reaches the print of a level, all inner levels were already evaluated and printed, reaching the reversed order.
The logic of the recursion is called post-order, in which you define your logic after the recursion call
Assume you have the following LinkedList 1->2->3->null
And you call
printReverse(head)
First will check if the head is null, if yes return (stop don't continue execution)
Second call printReverse by pointing to the next node
Third repeat steps 1 & 2 until hitting the null node
Four print the data
The result will print from the last node to the first node
I came across a traversing binary search tree function but I can't wrap my head around it. Here's the code:
public void inOrderTraverseTree(Node focusNode){
if(focusNode != null){
inOrderTraverseTree(focusNode.leftChild);
System.out.println(focusNode);
inOrderTraverseTree(focusNode.rightChild);
}
}
Assuming a "two-levels" balanced binary search tree, this is how I understand this recursive method:
Starting with root != null --> inOrderTraverseTree(root.leftChild) method runs
root.leftChild != null --> inOrderTraverseTree(root.leftChild.leftChild) method is runs
However, since root.leftChild has no leftChild --> focusNode.leftChild == null, the if loop will not run
in that case, isn't that supposed to mean that nothing ever gets printed?
But it supposedly works (https://www.youtube.com/watch?v=M6lYob8STMI). Can anyone point out where I've gone wrong?
The logic applied here:
Check the focused node. If null then return to parent's inOrderTraverseTree. But since nothing happens after the check for null, an additional return statement is same as no statement at all.
If not null, repeat from (1) for the left child node.
Print the value of the focused node.
Repeat from (1) for the right child node.
Return from current node's inOrderTraverseTree to parent node's inOrderTraverseTree.
Of course, if the focused node is the root node, inOrderTraverseTree simply returns to main, or the method that first invoked it
As an example, consider the tree below:
A
/ \
B C
/ \ / \
D E F G
Trace:
A->inOrderTraverseTree(left)
B->inOrderTraverseTree(left)
D->inOrderTraverseTree(left) //null, return to D
print(D)
D->inOrderTraverseTree(right) //null, return to D
return to B
print(B)
B->inOrderTraverseTree(right)
E->inOrderTraverseTree(left) //null, return to E
print(E)
E->inOrderTraverseTree(right) //null, return to E
return to B
return to A
print(A)
A->inOrderTraverseTree(right)
//Continue for the right subtree.
You need to understand the basic recursion and binary search tree structure here. Lets take below tree to understand this algorithm:
Steps:
1. Focus Node is 9 , since it is not null, thus , inOrderTraverseTree
is invoked with focus node as 7(with left node to 9)
2. Focus Node is 7 , since it is not null, thus , inOrderTraverseTree is invoked with focus node as null(with left
node to 7)
3. Focus Node is null , thus , if condition is not satisfied and execution of function call at step 2 continues.
4. Control goes to method call with node as 7 (since left node was blank) and 7 is printed at System.out.println statement.
5. Now inOrderTraverseTree for focus node null is invoked (with right node to 7)
6. Focus Node is null , thus , if condition is not satisfied and execution of function call at step 2 continues.
7. inOrderTraverseTree for focus node 2 exits and control goes to method call with node as 9.
8. Control goes to method call with node as 9 and 9 is printed at System.out.println statement.
9. inOrderTraverseTree for focus node 11 is invoked (with right node to 9)
10.inOrderTraverseTree for focus node null is invoked (with left node to 11), thus, if condition is not satisfied and control is sent
back to step 9
11. Control goes to method call with node as 11 and 11 is printed at System.out.println statement.
12.inOrderTraverseTree for focus node null is invoked (with right node to 11), thus, if condition is not satisfied and control is sent
back to step 9.
And the execution ends
However, since root.leftChild has no leftChild --> focusNode.leftChild
== null, the if loop will not run
No, it will. since it is recursive it will continue doing for previous calls, check for righchild node in this case.
watch the call order of the function:
it continues ...
Because of that to learn very-well logic of behind recursive idea, I'm practising while studying data structures by using debugger. The problem may seem easy but it just makes a sensation. The method finds maximum element in a binary search tree. - As a rule, binary search tree(click here for full implementation) is a tree in which left child has less elements than root element and right child has higher elements than root element. - Until finding it, the method goes into new activation frame and push it onto atop of the stack. Having been found, they are popped off in-reversed order(LIFO). My question is that why does the method return second statement(return findMax(node.right))? If the debugger shows activation frames being popped off, why does it just show the one time? I hope images aid to comprehend my question more as well.
/* bST.add(1),bST.add(3),bST.add(7),bST.add(6),bST.add(4),
bST.add(13),bST.add(14),bST.add(10),bST.add(8); */
/**
* Find max element in the BST
* #param node local node being given
* #return max element
*/
public E findMax(Node<E> node) {
if (node.right == null)
return node.data;
return findMax(node.right);
}
The code works down the right side of the tree until it hits the largest element: the one with no right child. Then it returns the data value of that node -- to the instance that called it. That was the instance called from node 13.
The particular statement return node.data is the base case for this recursion. The second one, return findMax(node.right), is the recursion case. By the time you reach the value 14, you have four of these returns stacked up, waiting for results.
The one from node 13 will then pass the value 14 back to the call from node 7, continuing down the stack until the call from node 1 returns the value 14 to whatever called findMax in the first place.
I don't know why your debugger shows evidence of only the first activation "pop". I don't know what settings you're using. If you're single-stepping, or have a breakpoint set at the return (as well as the findMax call), you should see both ends of that: going down another level, and then coming back up in LIFO order.
Does that clear up anything for you?
I am using a Breadth first search in a program that is trying to find and return the shortest path between two nodes on an unweighted digraph.
My program works like the wikipedia page psuedo code
The algorithm uses a queue data structure to store intermediate results as it traverses the graph, as follows:
Enqueue the root node
Dequeue a node and examine it
If the element sought is found in this node, quit the search and return a result.
Otherwise enqueue any successors (the direct child nodes) that have not yet been discovered.
If the queue is empty, every node on the graph has been examined – quit the search and return "not found".
If the queue is not empty, repeat from Step 2.
So I have been thinking of how to track number of steps made but I am having trouble with the limitations of java (I am not very knowledgeable of how java works). I originally was thinking that I could create some queue made up of a data type I made that stores steps and nodes, and as it traverses the graph it keeps track of the steps. If ever the goal is reached just simply return the steps.
I don't know how to make this work in java so I had to get rid of that idea and I moved on to using that wonky Queue = new LinkedList implementation of a queue. So basically I think it is a normal integer queue, I couldn't get my data type I made to work with it.
So now I have to find a more basic approach so I tried to use a simple counter, this doesn't work because the traversal algorithm searches down many paths before reaching the shortest one so I had an idea. I added a second queue that tracked steps, and I added a couple counters. Any time a node is added to the first queue I add to the counter, meaning I know that I am inspecting new nodes so I am not a distance further away. Once all those have been inspected I can then increase the step counter and any time a node is added to the first queue I add the step value to the step queue. The step queue is managed just like the node queue so that when the goal node is found the corresponding step should be the one to be dequeued out.
This doesn't work though and I was having a lot of problems with it, I am actually not sure why.
I deleted most of my code in panic and frustration but I will start to try and recreate it and post it here if anyone needs me to.
Were any of my ideas close and how can I make them work? I am sure there is a standard and simple way of doing this as well that I am not clever enough to see.
Code would help. What data structure are you using to store the partial or candidate solutions? You say your using a queue to store nodes to be examined, but really the objects stored in the queue should wrap some structure (e.g. List) that indicates the nodes traversed to get to the node to be examined. So, instead of simple Nodes being stored in the queue, some more complex object would be needed to make available the information necessary to know the complete path taken to that point. A simple node would only have information about itself, and it's children. But if you're examining node X, you also need to know how you arrived to node X. Just knowing node X isn't enough, and the only way (I know of) to know the path taken to node X is to store the path in the object that represents a "partial solution" or "candidate solution". If this is done, then finding the length of the path is trivial, because it's just the length of this list (or whichever data structure chosen). Hope I'm making some sense here. If not, post code and I'll take a look.
EDIT
These bits of code help show what I mean (they're by no means complete):
public class Solution {
List<Node> path;
}
Queue<Solution> q;
NOT
Queue<Node> q;
EDIT 2
If all you need is the length of the path, and not the path, per se, then try something like this:
public class Solution {
Node node; // whatever represents a node in you algorithm.
int len; // the length of the path to this node.
}
// Your queue:
LinkedList<Solution> q;
With this, before enqueuing a candidate solution (node), you do something like:
Solution sol = new Solution();
sol.node = childNodeToEnqueue;
sol.len = parentNode.len + 1;
q.add(sol);
The easiest solution in order to track distance during a traversal is to add a simple array (or a map if you vertices are not indexed by integers).
Here is pseudo code algorithm:
shortest_path(g, src, dst):
q = new empty queue
distances = int array of length order of g
for i = 0 to order: distances[i] = -1
distances[src] = 0
enqueue src in q
while q is not empty:
cur = pop next element in q
if cur is dst: return distances[dst]
foreach s in successors of cur in g:
if distances[s] == -1:
distances[s] = distances[cur] + 1
enqueue s in q
return not found
Note: order of a graph is the number of vertices
You don't need special data structures, the queue can just contains vertices' id (probably integers). In Java, LinkedList class implements the Queue interface, so it's a good candidate for your queue. For the distances array, if your vertices are identified by integers an integer array is enough, otherwise you need a kind of map.
You can also separate the vertex tainting (the -1 in my algo) using a separate boolean array or a set, but it's not really necessary and will waste some space.
If you want the path, you can also do that with a simple parent array: for each vertex you store its parent in the traversal, just add parent[s] = cur when you enqueue the successor. Then retrieving the path (in reverse order) is a simple like this:
path = new empty stack
cur = dst
while cur != src:
push cur in path
cur = parent[cur]
push src in path
And there you are …
I'm working alone on this project and could use another set of eyes to look at this to see what I am doing wrong. The first loop runs infinitely.
public void bfs(String start)
{
//Initial Case
add_queue.add(start);
graph.visit(start);
Iterator<String> neighbors;
String neighbor;
while(!add_queue.empty())
{
neighbors = graph.neighbors(start);
neighbor = neighbors.next();
graph.visit(neighbor);
add_queue.add(neighbor);
while(neighbors.hasNext())
{
neighbor = neighbors.next();
if(!graph.isVisited(neighbor)) //If vertex is not visited it is new and is added to the queue
{
add_queue.add(neighbor);
graph.visit(neighbor);
}
}
start = add_queue.remove();
remove_queue.add(start); //transfers vertex from add_queue to remove queue so that the order that the vertices were traversed is stored in memory
}
}
I think you are adding the first vertex of neighbours without checking if it's already visited.. here:
neighbor = neighbors.next(); <- you get first
graph.visit(neighbor); <- you visit
add_queue.add(neighbor); <- you add it without any check
while(neighbors.hasNext())
{
neighbor = neighbors.next();
if(!graph.isVisited(neighbor)) <- you do check for the others
{
add_queue.add(neighbor);
graph.visit(neighbor);
}
}
This means that you will never empty that queue.. since it starts with a size of 1, then you remove 1 element on each iteration but you add at least 1 element (you never add noone).
What's add_queue's definition of empty()?
It could be a bad naming issue, but it sounds like empty() does something, not just checks whether it is empty (which would be probably called isEmpty()).
Also, it looks like you always add at least 1 to add_queue in each outer loop (right before the inner while), but only remove one item from add_queue per iteration.
A few places to investigate:
Check to make sure that graph.isVisited() is actually recognizing when a node has been visited via graph.visit().
Is graph.neighbor(start) truly returning start's neighbors? And not including start in this list?
Your code is a little unclear. What exactly does graph.neighbors return?
In general to do a BFS you want to add the children of the current node to the queue, not the neighbors of it. Since it's all going into a queue this will ensure that you visit each node in the tree in the correct order. Assuming that it's a tree and not a general graph, this will also ensure that you don't visit a node more than once, allowing you to remove the checks to isVisited.
So, get the next node out of the queue, add all of it's children to the queue, visit the node, and repeat, until the queue is empty.