Im writing the method to print a binary search tree in order. I figured out a way to do this but it requires either the deletion or nullify nodes as they are printed. Below is my code:
public String printKeysInOrder() {
String output = "";
if (isEmpty()) return "()";
else{
int i = 0;
while(i!=size()){
Node x = root;
int loopBreak = 0;
while(loopBreak!=1){
if(x.left != null) x = x.left;
else if (x.right != null){
output = output + " " + x.val;
x.key = null;
x = x.right;
i++;
}
else{
output = output + " " + x.val;
x.key = null;
loopBreak = 1;
}
}
i++;
}
}
return output;
}
for the tree:
_7_
/ \
_3_ 8
/ \
1 6
\ /
2 4
\
5
it should print "1 2 3 4 5 6 7 8"
the code works in a way that it favors moving left through the tree until it can no longer go left, it then stores that node's value in the string output, makes the nodes key equal to null (as so future iterations of the loop do not go down that tree) and moves right if possible or iterates back around the loop.
Although i'm having trouble making it so the node equals null, as when the code is executed (via junit test) the code doesnt recognize that null key and goes through that subtree anyway? Can anyone help me out or tell me how to make it so the x.left and x.right pointers on future iterations recognize the node as null?
You don't need to nullify or delete nodes you need a traversal algorithm.
The in-order traversal provided here should work without major modification:
http://www.javabeat.net/binary-search-tree-traversal-java/
Another object-oriented approach to this is a Visitor supplied to an in-order traversable which allows you to supply the action performed at each node whether it be printing, collecting, mapping, or something else.
Related
I'm facing the classic "It works, but I don't know why!"-problem. I just applied a principle that I knew from another excercise with integers, but here I have to work with trees. The testing of the method was successfull. I am supposed to count the knots of a tree, and I do this bis traversing through it (in this case: inorder), and every time I traverse successfully (meaning: not facing an empty sub-tree), I count that as a knot. In this case, I'm wondering why this code doesn't count too much knots. For example, when I always go left and face an empty sub-tree, wouldn't I go up until I reach a knot where I can go right? Why does my code avoid this kind of problem?
public static int numberKnots (Tree b) {
int count = 0;
if (b.empty()) {
return 0;
}
else {
traverse.inorder(b.left());
traverse.inorder(b.right());
count = 1;
}
return count + numberKnots(b.left()) + numberKnots(b.right());
}
You do not really travel up and down the tree, you only travel down and visit each node once, and you do this by making your trees More and more simple.
Consider The following tree
a
/ \
b c
/ \
d e
So you start from the root and check if it is empty which it is not, so you return the result of 1 + numberKnots(left) + numberKnots(right). left and right are also trees and they are simpler than a
left right
b c
/ \
d e
So now you check the b tree, which is empty so it just returns 0. Then you check the c tree, which is not empty so you return 1 + countKnots(left (of c)) + countKnots(right (of c)) and so on.
Each step of the calculation would be:
countKnots(a)
= 1 + countKnots(b) + countKnots(c)
= 1 + 0 + countKnots(c)
= 1 + 0 + 1 + countKnots(d) + countKnots(e)
= 1 + 0 + 1 + 0 + countKnots(e)
= 1 + 0 + 1 + 0 + 0
= 2
Your code could be simplified to
public static int numberKnots (Tree b) {
if (b.empty()) {
return 0;
} else {
return 1 + numberKnots(b.left()) + numberKnots(b.right());
}
}
However, it does not seem to handle tree nodes which does not contain both left and right nodes, so the following tree would cause an error
a
\
c
Since you are using recursion,it does not transverse the same node twice.So your code works perfectly fine.consider (A) has two child nodes (B)&(C) further (B) has two childs (B1)&(B2).when transversing through recursion,it usses stack."(consider s to be our stack)". First the control reaches node(A) and since it has left child (A) is pushed into stack and control is trasferred to (B) now control is trasferred to (B)'s left child(B1) and (B) is pushed into stack, since (B1) does not have any childs it is counted and control is trasferred to top of stack i.e (B) and (B) is counted now control is trasffered to (B)'s right child it (B2)and (B2) is counted and control is trasferred to (B).Now (B) does not have any part of code left thus it is popped from stack and control is trasfered to (A) and (A) is counted and control is transfered to its right child (c).Similarly all nodes are counted without duplicating.
Hope it helps
I want to traverse a graph and return all paths that link 2 nodes where the first relationship is outgoing and the second is incoming. For example if the relationship is Voted and i want to see all possible paths from node 25 to node 86 i have MATCH p=((n {id:"25"}) -[*1..2]-> (m {id:"86"})) RETURN p; Then I want to check if in the returned path i have the same kind of property in the outgoing and incoming relationship (if they have the same vote).
I try to accomplish that with the graph traversal api in java but all i get back is a single path how can I get all possible paths in order to check them?
{it is basically a checking relationships with all common neighbors problem}
int common = 0;
int diff = 0;
for ( Path position : graphDb.traversalDescription()
.relationships(Wikilections_user.RelTypes.Voted, Direction.OUTGOING)
.relationships(Wikilections_user.RelTypes.Voted, Direction.INCOMING)
// .evaluator(Evaluators.fromDepth(1))
.evaluator(Evaluators.toDepth(2))
.evaluator(Evaluators.includeWhereEndNodeIs(node2))
// .evaluator(Evaluators.excludeStartPosition())
.traverse(node1))
{
Iterable<Relationship> myRels = position.reverseRelationships();
for (Relationship temp : myRels) {
System.out.println((temp.getStartNode()).getProperty("id") + " with " + temp.getProperty("with") + " :" + (temp.getEndNode()).getProperty("id"));
}
String with = "";
int i = 0;
for (Relationship temp : myRels) {
if (i == 0) {
with = (String) temp.getProperty("with");
i++;
}
if (i == 1) {
if (((String) temp.getProperty("with")).equals(with)) {
common++;
} else {
diff++;
}
}
}
}
return (double) common * 100 / (common + diff);
Traversals have uniqueness rules. Read that link, it talks about how the traverser works, and how you can configure it. By default, the uniqueness rules are set to NODE_GLOBAL meaning that a certain node cannot be traversed more than once.
I suspect this might be your problem; if you're looking for one target node, but you want all paths to that node, you should use RELATIONSHIP_GLOBAL instead, or one of the other options outlined by the documentation. Your traverser is looking for one end node, and by default you can only traverse that node once.
So to try this fix, add a different uniqueness to your traversal description:
graphDb.traversalDescription()
.relationships(Wikilections_user.RelTypes.Voted, Direction.OUTGOING)
.relationships(Wikilections_user.RelTypes.Voted, Direction.INCOMING)
.uniqueness( Uniqueness.RELATIONSHIP_GLOBAL );
This question already has answers here:
Java Printing a Binary Tree using Level-Order in a Specific Format
(23 answers)
Closed 8 years ago.
PS: This is NOT HOMEWORK. And I didn't understand the other question answer's, otherwise I wouldnt be opening a new one...
I'm trying to print this tree:
3
/ \
7 2
/ \ \
0 9 11
/ \ / \
1 2 6 4
As a level order output:
3
7 2
0 9 11
1 2 6 4
The problem is my code can only print trees like this: 3 7 2 0 9 11 1 2 64, which is the same as the last numbers but without a paragraph or '\n'. I can't seem to find an easy way to do this (preferencially without using foreach). Someone told me I should create a variable: 'level' on the tree that classifies in which level the node is, but how can I even classify the levels?
Can you help me?
public void largura() { //just an auxiliar method to call 'larguras'
larguras(root);
System.out.println();
}
private void larguras(Node t) {
LinkedList<Node> f = new LinkedList<Node>();
Node r;
f.add(t);
while (!f.isEmpty()) {
r=f.remove();
if (r!=root) System.out.print(" ");
System.out.print(r.value);
if (r.left != null) f.add(r.left);
if (r.right != null) f.add(r.right);
}
}
Hmmm... Would something like this work?
//Prints the tree in level order
public void printTree(){
printTree(root);
}
public void printTree(TreeNode tmpRoot){
//If the first node isn't null....continue on
if(tmpRoot != null){
Queue<TreeNode> currentLevel = new LinkedList<TreeNode>(); //Queue that holds the nodes on the current level
Queue<TreeNode> nextLevel = new LinkedList<TreeNode>(); //Queue the stores the nodes for the next level
int treeHeight = height(tmpRoot); //Stores the height of the current tree
int levelTotal = 0; //keeps track of the total levels printed so we don't pass the height and print a billion "null"s
//put the root on the currnt level's queue
currentLevel.add(tmpRoot);
//while there is still another level to print and we haven't gone past the tree's height
while(!currentLevel.isEmpty()&& (levelTotal< treeHeight)){
//Print the next node on the level, add its childen to the next level's queue, and dequeue the node...do this until the current level has been printed
while(!currentLevel.isEmpty()){
//Print the current value
System.out.print(currentLevel.peek().getValue()+" ");
//If there is a left pointer, put the node on the nextLevel's stack. If there is no ponter, add a node with a null value to the next level's stack
tmpRoot = currentLevel.peek().getLeft();
if(tmpRoot != null)
nextLevel.add(tmpRoot);
else
nextLevel.add(new TreeNode(null));
//If there is a right pointer, put the node on the nextLevel's stack. If there is no ponter, add a node with a null value to the next level's stack
tmpRoot = currentLevel.remove().getRight();
if(tmpRoot != null)
nextLevel.add(tmpRoot);
else
nextLevel.add(new TreeNode(null));
}//end while(!currentLevel.isEmpty())
//populate the currentLevel queue with items from the next level
while(!nextLevel.isEmpty()){
currentLevel.add(nextLevel.remove());
}
//Print a blank line to show height
System.out.println("");
//flag that we are working on the next level
levelTotal++;
}//end while(!currentLevel.isEmpty())
}//end if(tmpRoot != null)
}//end method printTree
public int height(){
return height(getRoot());
}
public int height(TreeNode tmpRoot){
if (tmpRoot == null)
return 0;
int leftHeight = height(tmpRoot.getLeft());
int rightHeight = height(tmpRoot.getRight());
if(leftHeight >= rightHeight)
return leftHeight + 1;
else
return rightHeight + 1;
Or perhaps something like this:
public void BFSPrint()
{
Queue<Node> q = new LinkedList<Node>();
q.offer(root);
BFSPrint(q);
}
private void BFSPrint(Queue<Node> q)
{
if(q.isEmpty())
return;
int qLen = q.size(),i=0;
/*limiting it to q size when it is passed,
this will make it print in next lines. if we use iterator instead,
we will again have same output as question, because iterator
will end only q empties*/
while(i<qLen)
{
Node current = q.remove();
System.out.print(current.data+" ");
if(current.left!=null)
q.offer(current.left);
if(current.right!=null)
q.offer(current.right);
i++;
}
System.out.println();
BFSPrint(q);
}
Essentially you are doing something like this:
http://leetcode.com/2010/09/printing-binary-tree-in-level-order.html
The code above will not work for a tree of more than 3 levels that's for you to figure out.
# commenter / -1'er I gave an example so they can play with it. It would appear that this is either homework or a sample exercise and I find playing with the code itself is more helpful to learning. Thats why I gave multiple implementations.
I'm trying to construct a binary tree (unbalanced), given its traversals. I'm currently doing preorder + inorder but when I figure this out postorder will be no issue at all.
I realize there are some question on the topic already but none of them seemed to answer my question. I've got a recursive method that takes the Preorder and the Inorder of a binary tree to reconstruct it, but is for some reason failing to link the root node with the subsequent children.
Note: I don't want a solution. I've been trying to figure this out for a few hours now and even jotted down the recursion on paper and everything seems fine... so I must be missing something subtle. Here's the code:
public static <T> BinaryNode<T> prePlusIn( T[] pre, T[] in)
{
if(pre.length != in.length)
throw new IllegalArgumentException();
BinaryNode<T> base = new BinaryNode();
base.element = pre[0]; // * Get root from the preorder traversal.
int indexOfRoot = -1 ;
if(pre.length == 0 && in.length == 0)
return null;
if(pre.length == 1 && in.length == 1 && pre[0].equals(in[0]))
return base; // * If both arrays are of size 1, element is a leaf.
for(int i = 0; i < in.length -1; i++){
if(in[i].equals(pre[0])){ // * Get the index of the root
indexOfRoot = i; // in the inorder traversal.
break;
}
} // * If we cannot, the tree cannot be constructed as the traversals differ.
if (indexOfRoot == -1) throw new IllegalArgumentException();
// * Now, we recursively set the left and right subtrees of
// the above "base" root node to whatever the new preorder
// and inorder traversals end up constructing.
T[] preleft = Arrays.copyOfRange(pre, 1, indexOfRoot + 1);
T[] preright = Arrays.copyOfRange(pre, indexOfRoot + 1, pre.length);
T[] inleft = Arrays.copyOfRange(in, 0, indexOfRoot);
T[] inright = Arrays.copyOfRange(in, indexOfRoot + 1, in.length);
base.left = prePlusIn( preleft, inleft); // * Construct left subtree.
base.right = prePlusIn( preright, inright); // * Construc right subtree.
return base; // * Return fully constructed tree
}
Basically, I construct additional arrays that house the pre- and inorder traversals of the left and right subtree (this seems terribly inefficient but I could not think of a better way with no helpers methods).
Any ideas would be quite appreciated.
Side note: While debugging it seems that the root note never receives the connections to the additional nodes (they remain null). From what I can see though, that should not happen...
EDIT: To clarify, the method is throwing the IllegalArgumentException # line 21 (else branch of the for loop, which should only be thrown if the traversals contain different elements.
EDIT2: Figured this out thanks to a helpful post from #Philip (coincidentally, we have the same first name... fun!). However, if anyone happens to have any advice on improving efficiency, I would appreciate the input.
this code is very suspicious to me
for(int i = 0; i < in.length -1; i++){
if(in[i].equals(base.element)){ // * Get the index of the root
indexOfRoot = i; // in the inorder traversal.
break;
} // * If we cannot, the tree cannot be constructed as the traversals differ.
else throw new IllegalArgumentException();
}
You enter the loop and i is set to 0, if i is less than in.length - 1 you evaluate the body of the loop which is an if expresion. At this point one of two things will happen
in[i] equals base.element in which case indexOfRoot will be set to 0 and you will break out of the loop
You throw an exception
Either way you never actually increment i
Try to rework this loop to do what you want, since it definitely isn't doing what you want now. You might try something like
int indexOfRoot = -1; //an impossible value
for(int i = 0; i < in.length -1; i++){
if(in[i].equals(base.element)){ // * Get the index of the root
indexOfRoot = i; // in the inorder traversal.
break;
}
}
if(indexOfRoot == -1){//if the root was never set
throw new IllegalArgumentException();
}
although that is still kinda ugly (for one thing, base.element never changes, so you might want to use pre[0] for clarity). And, by no means am I sure it is fully correct. Still, it is probably closer to what you want
I have a n-ary tree which contains key values (integers) in each node. I would like to calculate the minimum depth of the tree. Here is what I have come up with so far:
int min = 0;
private int getMinDepth(Node node, int counter, int temp){
if(node == null){
//if it is the first branch record min
//otherwise compare min to this value
//and record the minimum value
if(counter == 0){
temp = min;
}else{
temp = Math.min(temp, min);
min = 0;
}
counter++;//counter should increment by 1 when at end of branch
return temp;
}
min++;
getMinDepth(node.q1, counter, min);
getMinDepth(node.q2, counter, min);
getMinDepth(node.q3, counter, min);
getMinDepth(node.q4, counter, min);
return temp;
}
The code is called like so:
int minDepth = getMinDepth(root, 0, 0);
The idea is that if the tree is traversing down the first branch (branch number is tracked by counter), then we set the temp holder to store this branch depth. From then on, compare the next branch length and if it smaller, then make temp = that length. For some reason counter is not incrementing at all and always staying at zero. Anyone know what I am doing wrong?
I think you're better off doing a breadth-first search. Your current implementation tries to be depth-first, which means it could end up exploring the whole tree if the branches happen to be in an awkward order.
To do a breadth-first search, you need a queue (a ArrayDeque is probably the right choice). You'll then need a little class that holds a node and a depth. The algorithm goes a little something like this:
Queue<NodeWithDepth> q = new ArrayDeque<NodeWithDepth>();
q.add(new NodeWithDepth(root, 1));
while (true) {
NodeWithDepth nwd = q.remove();
if (hasNoChildren(nwd.node())) return nwd.depth();
if (nwd.node().q1 != null) q.add(new NodeWithDepth(nwd.node().q1, nwd.depth() + 1));
if (nwd.node().q2 != null) q.add(new NodeWithDepth(nwd.node().q2, nwd.depth() + 1));
if (nwd.node().q3 != null) q.add(new NodeWithDepth(nwd.node().q3, nwd.depth() + 1));
if (nwd.node().q4 != null) q.add(new NodeWithDepth(nwd.node().q4, nwd.depth() + 1));
}
This looks like it uses more memory than a depth-first search, but when you consider that stack frames consume memory, and that this will explore less of the tree than a depth-first search, you'll see that's not the case. Probably.
Anyway, see how you get on with it.
You are passing the counter variable by value, not by reference. Thus, any changes made to it are local to the current stack frame and are lost as soon as the function returns and that frame is popped of the stack. Java doesn't support passing primitives (or anything really) by reference, so you'd either have to pass it as a single element array or wrap it in an object to get the behavior you're looking for.
Here's a simpler (untested) version that avoids the need to pass a variable by reference:
private int getMinDepth(QuadTreeNode node){
if(node == null)
return 0;
return 1 + Math.min(
Math.min(getMinDepth(node.q1), getMinDepth(node.q2)),
Math.min(getMinDepth(node.q3), getMinDepth(node.q4)));
}
Both your version and the one above are inefficient because they search the entire tree, when really you only need to search down to the shallowest depth. To do it efficiently, use a queue to do a breadth-first search like Tom recommended. Note however, that the trade-off required to get this extra speed is the extra memory used by the queue.
Edit:
I decided to go ahead and write a breadth first search version that doesn't assume you have a class that keeps track of the nodes' depths (like Tom's NodeWithDepth). Once again, I haven't tested it or even compiled it... But I think it should be enough to get you going even if it doesn't work right out of the box. This version should perform faster on large, complex trees, but also uses more memory to store the queue.
private int getMinDepth(QuadTreeNode node){
// Handle the empty tree case
if(node == null)
return 0;
// Perform a breadth first search for the shallowest null child
// while keeping track of how deep into the tree we are.
LinkedList<QuadTreeNode> queue = new LinkedList<QuadTreeNode>();
queue.addLast(node);
int currentCountTilNextDepth = 1;
int nextCountTilNextDepth = 0;
int depth = 1;
while(!queue.isEmpty()){
// Check if we're transitioning to the next depth
if(currentCountTilNextDepth <= 0){
currentCountTilNextDepth = nextCountTilNextDepth;
nextCountTilNextDepth = 0;
depth++;
}
// If this node has a null child, we're done
QuadTreeNode node = queue.removeFirst();
if(node.q1 == null || node.q2 == null || node.q3 == null || node.q4 == null)
break;
// If it didn't have a null child, add all the children to the queue
queue.addLast(node.q1);
queue.addLast(node.q2);
queue.addLast(node.q3);
queue.addLast(node.q4);
// Housekeeping to keep track of when we need to increment our depth
nextCountTilNextDepth += 4;
currentCountTilNextDepth--;
}
// Return the depth of the shallowest node that had a null child
return depth;
}
Counter is always staying at zero because primitives in java are called by value. This means if you overwrite the value in a function call the caller won't see the change. Or if you're familiar with C++ notation it's foo(int x) instead of foo(int& x).
One solution would be to use an Integer object since objects are call-by-reference.
Since you're interested in the minimum depth a breadth first solution will work just fine, but you may get memory problems for large trees.
If you assume that the tree may become rather large an IDS solution would be the best. This way you'll get the time complexity of the breadth first variant with the space complexity of a depth first solution.
Here's a small example since IDS isn't as well known as its brethren (though much more useful for serious stuff!). I assume that every node has a list with children for simplicity (and since it's more general).
public static<T> int getMinDepth(Node<T> root) {
int depth = 0;
while (!getMinDepth(root, depth)) depth++;
return depth;
}
private static<T> boolean getMinDepth(Node<T> node, int depth) {
if (depth == 0)
return node.children.isEmpty();
for (Node<T> child : node.children)
if (getMinDepth(child, depth - 1)) return true;
return false;
}
For a short explanation see http://en.wikipedia.org/wiki/Iterative_deepening_depth-first_search