I have a BinaryTree and I want to get all nodes of a specific level. Order does not matter. I want to try to do this with recursion . My method looks like this:
public List<T> getNodesOnLevel(int i){
int recursionTool = i
//to do
recursionTool-=1
}
I tried to while(recursionTool != 0){ method.... and then recursionTool -1}
But I ended up getting all nodes until the wanted level.
My Node looks like this:
class Node<T>{
T val;
Node<T> left;
Node<T> right;
Node(T v){
val = v;
left = null;
right = null;
}
It is possible to implement this as a pure functional algorithm by concatenating the lists returned by recursive calls. Unfortunately, that is rather inefficient in Java because all retrieved values are copied by list creation or concatenation once at each recursion level.
If you are willing to use mutation, here is a solution that avoids the copying (assuming that this is a Node<T>):
private void getNodesOnLevel(int level, List<T> list) {
if (node == null) return;
if (level == 0) {
list.add(this.val);
} else {
this.left.getNodesOnLevel(level - 1, list);
this.right.getNodesOnLevel(level - 1, list);
}
}
The above method needs to be called with an empty (mutable) list as the 2nd argument, so we need another method:
public List<T> getNodesOnLevel(int level) {
List<T> list = new ArrayList<>();
this.getNodesOnLevel(level, list);
return list;
}
(In complexity terms, the pure functional solution is O(LN) where L is the level and N is the number of nodes at that level. My solution is O(N). Each value in the list will be copied twice on average, due to the way that ArrayList.append implements list resizing. The resizing could be avoided by creating the list with a capacity of 2level.)
This may help you. I had used this method to print nodes but you can change it.
public void printGivenLevel(TNode root, int level) {
if (root == null)
return;
if (level == 1 && root.getValue() != null) {
// here, add root.getValue() to list
} else if (level > 1) {
printGivenLevel(root.getLeft(), level - 1);
printGivenLevel(root.getRight(), level - 1);
}
}
Related
I wrote these method for my program and i felt that it is hard to read as there are too many loops, is there any other alternative to this code to make it look cleaner and easier to read
public static void printRoutingTable(Map <Node, List<Edge>> adj, Node Root)
{
for (Node thisNode : adj.keySet())
{
Node currentNode = thisNode;
String nextHop;
if(currentNode.getParent() != null){
do{
if(currentNode.getParent() != Root){
currentNode = currentNode.getParent();
nextHop = currentNode.getAddr();
}
else{
nextHop = currentNode.getAddr() ;
}
}
while(currentNode.getParent() != Root);
}
else
{
nextHop = ""+currentNode.getAddr();
}
nextHop = nextHop.trim();
}
}
I've not tried, but this should be a functional and recursive version of your code.
String getNextAddr(Node node, StringBuilder sb, Node root) {
sb.add(node.getAddr());
if (node.getParent() != null && node.getParent() != root) {
return getNextAddr(node.getParent(), sb);
}
return sb.toString();
}
String nextHopList =
adj.keySet()
.stream()
.map(k -> getNextAddr(k, new StringBuilder(), Root))
.collect(Collectors.toList())
It's difficult to tell what your code is trying to achieve. At the moment it's not actually doing anything because the nextHop variable is local and nothing seems to be accumulated in the loop. I'm assuming you intend to join the strings your are generating.
there's no point passing in a map if you aren't going to use it. Better to pass a collection (or, better, Stream) of nodes.
generally the root node is the only one with a null parent. So it's likely you also don't need to pass in a reference to the root node.
if parent is optional I suggest you return Optional<Node> from getParent rather than Node.
an easy way to make the code easier to read is to break the parts into separate methods that are named after exactly what they do.
So taking these suggestions into account, something like the following:
String getRoutingTable(Stream<Node> nodes) {
return nodes
.flatMap(this::getRoutingForNode)
.map(Node::getAddr)
.collect(joining(";"));
}
private Stream<Node> getRoutingForNode(Node node) {
Stream.Builder<Node> pathToRoot = Stream.builder();
for (Node c = node; c.getParent().isPresent(); c = node.getParent().get()) {
pathToRoot.accept(c);
}
return pathToRoot.build();
}
Note that in Java 9 the getRoutingForNode will become much more readable as you will be able to dispense with the Builder:
return Stream.iterate(node,
n -> node.getParent().isPresent(),
n -> n.getParent().get());
I am trying to write a code to convert a binary tree to a lists of nodes with same depth. If a tree has depth d, then d lists will be created. The logic is to do in-order traversal and add the currently traversed node to the list of appropriate depth.
public void treeToListofNodesByLevel(Node<T> n,int depth, ArrayList<LinkedList<Node<T>>> treeList){
if(n.right != null){
inOrderWithHeight(n.right, depth + 1);
}
if(treeList.size() >= depth){
treeList.add(depth, new LinkedList<Node<T>>() );
}
treeList.get(depth).add(n);
if(n.left != null){
inOrderWithHeight(n.left, depth + 1);
}
}
and then calling:
ArrayList<LinkedList<Node<T>>> result = new ArrayList<LinkedList<Node<T>>>();
treeToListofNodesByLevel(root, 0, result);
Will this work ? Are there any corner cases I am not handling ?
Also, right now I am passing the List of List to be returned by the method because I can not think of a way to initialize it in the method and returning it at then end while also maintaining the recursive structure. Is there a better way to do this ?
You have the general concept pretty much perfect. It will work, and should handle all cases.
However, you have a few errors in the details:
Your check for when to add a new list has the comparison in the wrong direction. It should be if (treeList.size() <= depth).
Each call to inOrderWithHeight() (which you haven't provided any code of) should be a recursive call to treeToListofNodesByLevel(). Keep the first two arguments as they are, and just pass the treeList for the third.
This one's more a style issue, but parameter types should generally be declared as the highest level type that satisfies what you actually need. There is no need here to specify ArrayList or LinkedList, any List will do. Change the treeList parameter's type to List<List<Node<T>>>.
For the matter of initializing the List inside the method while also using recursion, that's the sort of thing that implementation helper methods are for. Take the current body of treeToListofNodesByLevel and move it into a private method (with the recursive calls changed so the private method calls itself), let's call it treeToListofNodesByLevelHelper. Then change the current public method to this:
public List<List<Node<T>>> treeToListofNodesByLevel(Node<T> node) {
List<List<Node<T>>> result = new ArrayList<>();
treeToListofNodesByLevelHelper(node, 0, result);
return result;
}
I cannot understand what the method "inOrderWithHeight" is doing. What I do for this question (not optimized) is to traverse like BFS using two queues and for each iteration adding the nodes of that depth to the list of that iteration (each iteration is traversing one depth of the tree). Here is my code to do that for a binary tree as you supposed in your answer:
Queue<Node<T>> queue1 = new LinkedList<Node<T>>() ;
Queue<Node<T>> queue2 = new LinkedList<Node<T>>() ;
public void treeToListofNodesByLevel(Node<T> root, ArrayList<LinkedList<Node<T>>> treeList) {
if (root == null)
return;
int curr_depth = 0;
queue1.add(root);
while(!queue1.isEmpty()){
treeList.add(curr_depth, new LinkedList<Node<T>>());
while(!queue1.isEmpty()){
Node<T> node = queue1.remove();
treeList.get(curr_depth).add(node);
if(node.left != null) queue2.add(node.left);
if(node.right != null) queue2.add(node.right);
}
curr_depth++;
while(!queue2.isEmpty()){
Node<T> node = queue2.remove();
queue1.add(node);
}
}
}
I wrote this on the fly without syntax checking and may have compiler errors. But hopefully you get the idea.
Why you just use the same function the code will be more beautifull :
public void treeToListofNodesByLevel(BinaryTree node, int currentDepth, List<List<BinaryTree>> result){
// Check if the list for the currentDepth is created
if(result.get(currentDepth) != null){
result.add(currentDepth, new ArrayList<BinaryTree>())
}
// Add the current node to the list
result.get(currentDepth).add(node);
// Recursive the left node
if(node.left != null){
treeToListofNodesByLevel(node.left, currentDepth+1, result);
}
// Recursive the right node
if(node.right != null){
treeToListofNodesByLevel(node.right, currentDepth+1, result);
}
}
In your main function :
List<List<BinaryTree>> result = new ArrayList<>();
BinaryTree root = new BinaryTree();
treeToListofNodesByLevel(root, 0, result);
So I just wrote code for insertion of nodes in binary tree (NOT BST).
I noticed that every time the recursive insert returns a 'node', it is assigned to the initial node.
Does this mean, that the memory reference of root of this tree would change on the completion of each insert?
public void add(int data)
{
root=add(root,data);
}
public static BinaryNode add(BinaryNode node, int data) {
if(node==null)
{
node=new BinaryNode(data);
}
else {
///IF not 1st element, flow enters this part
if(node.left==null && node.right==null)
{
node.left=add(node.right,data);
}
else if (node.right == null) {
node.right=add(node.right, data);
} else {
node.left=add(node.left, data);
}
}
return node;
}
Within add the only time you change node is if the tree at that point is empty, so the answer is no except for the first insert.
However, note that you add a new level to the tree only on the left (first if condition) so the "tree" you build is highly unbalanced to the left. This isn't really a "tree", it's more like a strange linked list. Also, since you don't maintain any particular sequence it can't be better than a simple unordered list for searches.
Is there a way to recursively traverse a tree and return an array that is scoped to that recursive method?
So I recently answered someone else's question on this topic. That question can be found here: SO Question. My solution uses an array outside of the scope of the recursion, and therefore the method cannot (or at least probably should not) return the array. However, is there a way to write a recursive method for traversing trees such that it returns an array? Even writing an initial method that calls the recursive one would be fine, but I can't think of a good way to do this.
Here's the code that I suggested before:
private List nodeValues = new ArrayList();
public void traversePreRecursive(BinarySearchTreeNode node)
{
if (node != null)
{
nodeValues.add(node.getValue());
traversePreRecursive(node.getLeft());
traversePreRecursive(node.getRight());
}
}
As you can see the ArrayList is outside of the scope of the recursion - And therefore returning it doesn't make a lot of sense. Is there a better way to do this?
public static List traversePreRecursive(Node node) {
if (node == null) return new ArrayList();
List nodeValues = new ArrayList();
nodeValues.add(node.getValue());
nodeValues.addAll(traversePreRecursive(node.getLeft()));
nodeValues.addAll(traversePreRecursive(node.getRight()));
return nodeValues;
}
There is an alternative, but it involves two passes over the tree. You would only employ this alternative if the array operations in my first answer were giving you grief. This approach starts by providing an index for each of the nodes (the index() method) -- basically working out which element of the array a node should occupy before we actually create the array. This also gives me a count of nodes (size). I then allocate an array (list) big enough to hold all the nodes and pass it into a method (addToList) that copies the node-references into the previously identified element in the array.
public static List<Node> getNodes(Node a) {
int size = index(a, 0);
List<Node> list = new ArrayList<Node>(size);
addToList(a, list);
return list;
}
private static int index(Node node, int index) {
if (node == null) return index;
node.setIndex(index);
int iLeft = index(node.getLeft(), index++);
int iRight = index(node.getRight(), iLeft++);
return iRight + 1;
}
private static void addToList(Node node, List<Node> list) {
if(node == null) return;
list.add(node.getIndex(), node);
addToList(node.getLeft(), list);
addToList(node.getRight(), list);
}
In c you can have static function variables,(Ie, adding a value to a list in one iteration of a function means that that value will be in the list in the next iteration--if the list is static) but using them isn't the best (most optimal) solution for the problem you are suggesting. So, I think you are searching for static variables, but this isn't an appropriate case to use them.
I tried to convert a List from 3{1{,2{,}},5{4{,},6{,}}}
to a Binary Tree like this
3
1 5
2 4 6
I thought it would be easier to use recursion but I get stuck.
public void ListToTree (ArrayList al) {
Iterator it = al.iterator();
// n is the Tree's root
BSTnode n = new BSTnode(it.next());
recurse(al,it,n);
}
void recurse (ArrayList al, Iterator it, BSTnode n) {
if(!it.hasNext()) return;
Object element = it.next();
if(element=="{"){
recurse(al,it,n.left());
return;
} else if (element==",") {
recurse(al,it,n.right());
return;
} else if (element =="}") {
}
}
I don't know how to proceed and was wondering if it's the right track. Please give me some hints how to solve it. Moreover, I realize I often get stuck on recursive questions. Is it because I always want to break it down? Should I just think top-down and double-check if it's correct? Thanks in advance !
Firstly: are you bound to that terrible list representation? You can easily build a BST based on the BST rules with this code:
void insert(Node n, int value) {
if(n == null) {
n = new Node(value);
} else if(value < n.value) {
if(n.left == null) {
n.left = new Node(value);
return;
}
insert(n.left, value);
} else if(value > n.value) {
if(n.right == null) {
n.right = new Node(value);
return;
}
insert(n.right, value);
}
}
You really don't have to pass the iterator. Just use the values from the list. Also it is usually unadvised to use implementation types in method signatures. (i.e. ArrayList -> List).
Another big mistake here is that you don't use == for value comparison, that is for reference comparison. Use equals instead, but you should downcast the Object after an instanceof test e.g.:
if( element instanceof String) {
String seperator = (String)element;
if("{".equals(separator))
//do sth...
Btw the thing you are missing from the code is the actual insertion and the backwards navigation.
After you found the right subtree by navigating with the {-s and ,-s, check whether the element is an Integer then set it as a value for the current node. Backwards navigation should be in the } branch by either returning one level from the recusion and some tricks or calling the method on the parent of the actual node.
But I don't suggest you to follow this direction, it is much easier to just use the values from the list and the simple insertion method.