I am working on assignment for school. It manly consists of a method that takes as input a binary tree and returns a double threaded tree. Eg(if left child = null then left child will be connected with preceding inorder parent and if right child = null the it will link to its inorder succesor. Now I have an idea for the implementation...
I iterate recursively trough the original BINARY tree and store into an array the inorder traversal. Now, because my teachers implementation requires that threaded trees be a different class from binary. I must traverse again trough the binary tree and convert each node from binaryNode to threadedNode thus having at the end a "duplicate" of the initial BinaryTree but as Threadedtree type. After I do this I traverse again trough this threadedTree and whenever i see a null left or right child I refer to the inorder arraylist and find the threads.
Now as you might have noticed this is extremely inefficient, i am essentially traversing the tree 3 times. My professor has stated that this could be done recursively with only one traversal, essentially converting to threadedNode and finding the threads all at once. I have tried multiple ways but i can not find one that works. Does anyone have any kind of tip or some way i can implement it? Thanks
This is the method as specified by the instructor
public static <T> ThreadedNode<T> thread(BinaryNode<T> root)
{
//threads a binary tree
}
The instructor is correct. One traversal is sufficient.
Traverse the original binary tree, creating new ThreadedNodes as you walk this tree.
public static <T> ThreadedNode<T> thread(BinaryNode<T> root) {
// We'll be keeping track of the "previous" node as we go, so use
// a recursive helper method. At first, there is no previous.
return threadHelper(root, null);
}
private static <T> ThreadedNode<T> threadHelper(BinaryNode<T> n, ThreadedNode<T> previous) {
// Create a new threaded node from the current root. Note that the threaded nodes
// are actually created in "preorder". Assume the ThreadedNode constructor sets
// the left, right, threadLeft, and threadRight fields to null.
ThreadedNode<T> t = new ThreadedNode<T>(n.getData());
// First go down the left side, if necessary.
if (n.getLeft() != null) {
// If there is a left child we have to descend. Note that as we go down the
// left side the previous doesn't change, until we start "backing up".
t.left = threadHelper(n.getLeft(), previous);
previous = t.left;
} else {
// If there is no left child, connect our left thread to the previous.
t.threadLeft = previous;
}
// Now before we go down the right side, see if the previous
// node (it will be in the left subtree) needs to point here.
if (previous != null && previous.right == null) {
previous.threadRight = t;
}
if (n.getRight() != null) {
// If there is a right child we can descend the right. As we go down we
// update previous to the current node. We do this just by passing the current
// node as the second parameter.
t.right = threadHelper(n.getRight(), t);
} else {
// No right child, no worries. We'll hook up our thread-right pointer
// later.
}
return t;
}
Consider the tree (A (B (D) ()) C). The first node you hit in an inorder traversal is D. There is no previous node. So save D as previous. Then the next node you hit is B. The previous node was D, which had no right child, so add a threaded right pointer from D to B. Then set previous to B and continue. Next you hit A. B had no right child, so add a threaded right link from B to A. A has a right child so continue, setting previous to A. The next node is C. C has no left child, so add a threaded left link from C to the current value of previous, which is A.
You could skip the second trip of traversal that you mention in your method. You could convert the nodes from BinaryNode to ThreadedNode on the fly. You'd still need to traverse twice, I think, for the inorder traversal, and for finding the threads and converting it to aThreadedTree.
For conversion on the fly, you could use the method that your instructor has given.
HTH!
Related
My method should add the associated key/value pair to the trie and if the key is already in the trie, the value should be updated. However I am not quite sure what Im doing wrong, its my first time using tries.
So I am currently working on my put method and I have the following:
public void put(TrieMapNode current, String curKey, String value){
if(current.getChildren().containsKey(curKey))
value = current.get(key);
curKey =value;
put(current.getChildren().get(curKey), curKey, value);
}
Any help would be greatly appreciated thanks!
In your current implementation, you will not benefit from the advantages of a trie. That is because at the root node, you have one child for each string you encounter.
That is not the way a trie is built. Each node of your trie can have at most one child per character (the elements that form strings).
So your method should look more like the following:
public void put(TrieMapNode current, String key, String value, int depth){
if (depth == key.length()){
current.value = value;
} else {
char curChar = key.charAt(depth);
if(!current.getChildren().containsKey(curChar)){
TrieMapNode newNode = new TrieMapNode();
current.getChildren().put(curChar, newNode);
}
put(current.getChildren().get(curChar), curKey, value, depth + 1);
}
The main mistake you did was to consider the key as a whole when inserting/updating in your trie. This would have resulted in a root node having one child node for each key in your map (so a ton of children), but with a very limited depth (the root node, its children and that's it).
In the implementation I proposed you, a node has one child per possible character (a bounded number, 26, 52, anyway a small and bounded number).
And its depth is not limited to one, because as you can see in the else block, we create a node if the one we look for did not exist (when you start you only have a root node, so you need to plan for the case where new node are created), and we also call recursively put on a child of the current node. So the value will be stored at a depth equal toi the length of its key.
java version "1.8.0_92"
I am studying trees and how to traverse them using recursion. But I am confused about it works.
public void preOrder(BinaryTree root) {
if(root != null) {
System.out.println(root);
preOrder(root.leftChild); <-- this gets called and will start from the top of the function
preOrder(root.rightChild); <-- how can this get called if the top one will always calls itself?
}
}
I think that the second preOrder will never get called as the call above will always call itself so the second one will never be executed.
It does not always call itself. It keeps going until it bottoms out with a null leftChild. Then execution returns without doing anything -- it backs up one level and recurs on the rightChild of the lowest-level parent node. When that call also runs out of children, the execution returns from handling this lowest-level parent node, again backing up one call, and does the rightChild of that node ... until the entire tree has been traversed.
Think of it has as opening up a whole bunch of doors until you find what you're looking for, then you have to go back and close/check the other ones.
public void preOrder(BinaryTree root) {
if(root != null) {
System.out.println(root);
preOrder(root.leftChild); <-- this gets called and will start from the top of the function
preOrder(root.rightChild); <-- how can this get called if the top one will always calls itself?
}
}
We can replace the preOrder calls with the matching code to look like:
public void preOrder(BinaryTree root) {
if(root != null) { <-- note the if check
System.out.println(root);
if(root.leftChild!= null) { <-- note the if check
System.out.println(root.leftChild.leftChild);
preOrder(root.leftChild.leftChild); <- this expands into another if block
preOrder(root.leftChild.rightChild); <- this also expands
}
if(root.rightChild!= null) { <-- note the if check
System.out.println(root.rightChild.leftChild);
preOrder(root.rightChild.leftChild);
preOrder(root.rightChild.rightChild);
}
}
}
It keeps expanding outwards... until you hit the special "base" if conditional that stops the recursion. In this case it is when you've found a leaf node of the tree, i.e. node == null, it stops the expansion because the if conditional is no longer true and everything begins to collapse in on itself, or in other words it can continue executing normally down the block of code.
Recursion may seem to be confused when you just start to learn. Firstly, you can think of a subproblem. For preOder, it always prints out the root node, and left node, then right node. All you need is to solve a subproblem. (a basic simple tree below)
root
/ \
left right
/ \
... ...
Now go back to look at the code:
if(root != null) {
System.out.println(root);
preOrder(root.leftChild); // the left node now becomes another root, and keep making the next left node root until the next left node is null.
preOrder(root.rightChild); // this line of code won't be executed until the last preOrder function call its root == null(hit the condition.)
}
Trust recursion; it will always do the rest of part for you if your condition is correct. I agree to run debug mode to have a better understanding. It is very useful to learn how to use "step in" when you try to understand how code works.
Once root.leftChild becomes null (ie, when you get to a leaf of the tree), preOrder will be called like so: preOrder(null). When this happens, the condition will evaluate to false, and recursion unwind and stop, at which point preOrder(root.rightChild) will be evaluated.
Here's a call trace (in Scala):
case class BinaryTree(nodeName: String, leftChild: Option[BinaryTree], rightChild: Option[BinaryTree]) {
def preOrder(root: Option[BinaryTree], depth: Int = 0) {
root match {
case Some(root) => {
println(" " * depth + root.nodeName)
preOrder(root.leftChild, depth+4)
preOrder(root.rightChild, depth+4)
}
case None => println(" " * depth + "leaf")
}
}
}
val tree = new BinaryTree(
"root",
Some(new BinaryTree(
"a",
Some(new BinaryTree("aa", None, None)),
Some(new BinaryTree("ab", None, None)))),
Some(new BinaryTree(
"b",
Some(new BinaryTree("ba", None, None)),
Some(new BinaryTree("bb", None, None)))))
tree.preOrder(Some(tree))
root
a
aa
leaf
leaf
ab
leaf
leaf
b
ba
leaf
leaf
bb
leaf
leaf
From a binary tree, you want to create a 2-d arraylist where each arraylist within the main arraylist contains all the nodes of a binary tree on a single level, for all of the levels. I understand how to do this recursively with DFS but I am very confused about why it possible to get the correct answer by passing in the arraylist I want to populate as a parameter in the recursive function.
The header of my recursive function looks like this
createLevelLinkedList(TreeNode current, ArrayList<LinkedList<TreeNode>> lists, int level)
With basecase:
if (current == null) return;
As the tree is traversed, the current node will be appended to its corresponding arraylist within "lists". Within the recursive function there there two recursive calls to move the function to the child nodes of current:
createLevelLinkedList(current.left, lists, level + 1);
createLevelLinkedList(current.right, lists, level + 1);
Suppose there is a tree that looks like this
5
3 8
2 4 9
With depth first tree traversal, after the first return, we will have TreeNode "2" is the top object in the stack, then "3". When TreeNode "3" is current and the function calls
createLevelLinkedList(current.right, lists, level + 1);
To push TreeNode "4" onto the stack, how can lists contains TreeNode "2" if it actually does and what is really going in memory?
The code I am referencing can be found on Github: https://github.com/gaylemcd/ctci/blob/master/java/Chapter%204/Question4_4/QuestionDFS.java
public static void createLevelLinkedList(TreeNode root, ArrayList<LinkedList<TreeNode>> lists, int level)
{
if (root == null) return;
LinkedList<TreeNode> list = null;
if (lists.size() == level) { // Level not contained in list
list = new LinkedList<TreeNode>();
/* Levels are always traversed in order. So, if this is the first time we've visited level i,
* we must have seen levels 0 through i - 1. We can therefore safely add the level at the end. */
lists.add(list);
} else {
list = lists.get(level);
}
list.add(root);
createLevelLinkedList(root.left, lists, level + 1);
createLevelLinkedList(root.right, lists, level + 1);
}
You should understand that there's only one ArrayList instance passed to the createLevelLinkedList method. Each recursive call to createLevelLinkedList receives a reference to the same instance of the ArrayList.
Therefore, once the TreeNode 2 is added to the ArrayList (or, to be exact, to one of the LinkedLists contained within the ArrayList), it stays there throughout the execution of the recursive method. It doesn't disappear when the invocation of createLevelLinkedList that added it to the list returns.
I'm trying to create a queue using two classes, a Node class and a Queue class for an assignment. Here's the node class:
class Node
{
protected Node next;
public Node()
{
next = null;
}
}
This class basically links the data together using a Node.next object. I've successfully been able to create a stack with push() and pop(), because the two operations happen on the same end, so the point are just manipulated between pointing to a new added node, and the previous node.
However, I'm having some difficulties understanding the logic to create a queue based on a similar structure. My queue class looks something like this:
class Queue
{
private Node footer;
private Node header;
public Queue()
{
footer = null;
header = null;
}
public void add(Node newNode)
{
//Adds onto the queue from the 'footer' end.
}
public Node remove()
{
//Removes from the queue from the 'header' end.
}
Here's what I understand: (1)The header and the footer point to the same first node. (2) Subsequent adding should change the footer to point to the added nodes, but the header stays on the first node added. (3) The header should point to the next oldest node upon removal.
Here's what I can't figure out (and where it's different than popping from a stack). How do I get the header to point to the 'next oldest node', given that I have more than 2 nodes in this queue? I know I can do this if I link header.next to the next node in the queue, but how can I access the next node so that it can point to it?
I thought about how in add(), the newNode.next should point to the next newNode (reverse direction of a Stack), but this can't work because the next newNode isn't in existence yet.. Another idea was to modify the Node class to have a Node.previous for a way to point backwards, but I would be breaking specification for this assignment.
My instructor hinted something about "header.next will point for second item as header and footer point to first node initially," and that the way to do this is pretty simple. However, I've been drawing how this works, and I'm confused how the initial pointing to the same node will allow header.next to "automatically" point to the next oldest node, especially if more and more nodes are added and the footer eventually is separated from the header by more than 2 nodes. Is there something about OOP I'm not seeing?
Any help would be great!
To expand on, and offer a subtle alternative to #Sanjeev's answer (one that I think your instructor was hinting to):
Rather than using footer to store "actual" nodes, use it as a placeholder: Declare it as a final variable, initialize it in your constructor and make sure that either a) it's next node is always your header (this would be called a circular list), or its next node is null.
Can you see how this solves your "this can't work because the next newNode isn't in existence yet" problem: Of course you can't point the last node added to the next one that will be added before adding it - instead, you point it to this "dummy" node - which is a placeholder for the next node that will be added, when and if it is.
add(Node newestNode){
identify the last node added as the one whose next property is the footer.
change the next property of that node from footer to this new newestNode
set the next property of this new newestNode to footer
}
It would be preferable to identify that last node added as the one that footer is pointing to (rather than the one pointing to footer), which would be easy if you were allowed to have previous as well as next properties on nodes, but it sounds like you're not allowed to do that. Of course, since we're using footer as a "dummy node", we could simply use footer.next the way we would footer.previous and have it point backwards instead of forwards, but I'll leave you to consider how clean that would be. There are other options here that I'll leave you to consider as well.
How do I get the header to point to the 'next oldest node'`
The "oldest" node was the first one added. The "newest" node is the last one added. How is the order of the rest of the nodes stored? The same way it was in your Stack - by traversing a chain of references stored as instance variables on your nodes. The main point I want to make is that Stacks and Queues, when implemented as linked data structures, are much more similar than you seem to be thinking, at least from a : Iterating through any linked data structure is done by following traversing these links - don't get too hung up on the fact that you're "moving" in a different direction - the same basic principles apply:
Node remove(){
identify the "oldest" node as header.next.
Store a reference to that node so you can return it.
identify the "second oldest node" as header.next.next
change header.next to header.next.next
return the reference to the old header.next you saved above.
(Note that using header/footer as placeholders, rather than storing "actual" nodes in them as #Sanjeev suggests, is not necessary, but it'll make your life easier - for instance, by helping you avoid a lot of null checking)
Here is the sudo code that will help you get started.
public void add(Node newNode)
{
if footer is null ?
then
header = newNode and footer = newNode;
else
footer.next = newNode and footer = newNode;
end if
}
public Node remove()
{
Node returnMe = header;
if header is not null?
then
header = header.next
if header is null
then
footer = null;
endif
end if
return returnMe;
}
How do I get the header to point to the 'next oldest node', given that
I have more than 2 nodes in this queue? I know I can do this if I link
header.next to the next node in the queue, but how can I access the
next node so that it can point to it?
To make header point to that node, you only need do header = header.next. The reason is that Java objectt assignment is by reference. Since header.next is type of Node, header is type of Node, it will copy the address of header.next to header, i.e., header is advanced one place.
I thought about how in add(), the newNode.next should point to the
next newNode (reverse direction of a Stack), but this can't work
because the next newNode isn't in existence yet..
I think it is no need to considering reverse direction. The reason is because for adding , it is to add element to the tail/footer of the queue. The only special case is that the queue didn't have any elements (footer == header == null), 1 element : (footer = header = element), other case: header won't change, but you need to append element to footer, and then make footer point to the new node.
When only 1 element, footer.next == header.next == null
The first thing that you need to do is make sure the first node you create is the oldest so it should be the first to be removed from the Queue based on First In First Out (FIFO) principle to archive this you might need to modify you're add method to something like this, by the way this example is based on single linked list implementation.
void add(char new_data)
{
/* 1. alloc the Node and put data*/
Node new_Node = new Node(new_data);
/* 2. Make next of new Node as head */
new_Node.next = head;
/* 3. Move the head to point to new Node */
head = new_Node;
}
then you will need a remove method which will remove the oldest node on the list first remember in Queue the order of remove is First In First Out (FIFO)
that being said this remove method should help you
void remove()
{
// Store head node
Node temp = head, prev = null;
// If head node itself holds the key to be deleted
if (temp != null )
{
head = temp.next; // Changed head
return;
}
// Search for the key to be deleted, keep track of the
// previous node as we need to change temp.next
while (temp != null)
{
prev = temp;
temp = temp.next;
}
// If key was not present in linked list
if (temp == null) return;
// Unlink the node from linked list
prev.next = temp.next;
}
This worked for me on my linked list
So, I'm making my own implementation of a Binary Search Tree. In doing so, I've come across an unusual issue, and I have no idea why it's occurring.
setNode Method:
// Sets the Node at the specified Index
public void setNode(int index, NodeInterface<E> node)
{
if(index < 0 || index >= degree)
throw new ArrayIndexOutOfBoundsException("Index: " + index + ", Size: " + nodes.size());
nodes.set(index, (Node<E>) node);
}
The variable nodes is an Array List of Nodes, if that is important.
Now this is where things begin to get messy, being where the error is occurring. It's in the addDescendant method within the BinaryNode Class, which extends the Node class.
addDescendant Method:
// Adds the specified Descendant to this Node
public boolean addDescendant(BinaryNode<E> node)
{
// Determine Node Type
if(compareTo(node) > 0) // Make Left Child
{
if(hasLeftChild())
return getLeftChild().addDescendant(node);
else
{
setNode(0, node); // Link Parent to Child
// ^^^ Works Fine ^^^
node.setNode(1, hasRightChild() ? getRightChild() : this); // Link Child to Parent or Sibling
// ^^^ Does not Work ^^^
return true;
}
}
else if(compareTo(node) < 0) // Make Right Child
{
if(hasRightChild()) // Node already has a Right Child
return getRightChild().addDescendant(node);
else // Node does not have a Right Child
{
if(hasLeftChild())
{
getLeftChild().setNode(1, node); // Link Sibling to Sibling
// ^^^ Does not Work ^^^
}
else
{
setNode(0, node); // Link Parent to Child for the time being
// ^^^ Works Fine ^^^
}
node.setNode(1, this); // Link Child to Parent
// ^^^ Does not Work ^^^
return true;
}
}
else // Duplicate Node
return false;
}
The two important things to note here are the uses of the setNode. It works fine when I use the index of 0, but doesn't work when I use the index of 1.
I'm not getting any errors or warnings, and the code seems to run as it should, but the results are not what I'm expecting.
The method doesn't set the Right Node properly, despite it using the same method to set the Left Node, and that works fine.
I hope I've given enough information, I didn't want to bombard everyone with code.
Unrelated Note:
If you're confused by the connection of my tree, that's because it's not your typical Binary Search Tree. However, the actual structure of the tree shouldn't matter.
Not much information. But I will try:
I think you tree is more unary than binary.
If an index of 1 marks the right child of a node
but also marks the parent of a node, the logic seems
somehow broken to me.
Second thing is in the 'Make left child' part of addDescendant:
It can happen that that more than 2 nodes have the 'root' node
connected to their index 1.
At 'Make Right Child' part of addDescendant:
getLeftChild().setNode(1, node);
Changing nodes of child nodes without further checkings
(by not-using its addDescendant method) is not a good idea.