I need to find the number of elements in a tree using an iterative algorithm, but I'm finding the code conceptually very difficult to write.
My approach is to start at the root node and visit the child nodes, then the children of these child nodes, and so on.
This is the code I've written which works for a small tree, but isn't a real solution because I'd need to add an additional block for each level of depth:
// Start the counter at 1 because the root node counts
int size = 1;
for(ITree child1 : root) {
size++;
for(ITree child2 : child1) {
size++;
for(ITree child3 : child2) {
size++;
for(ITree child4 : child3) {
size++;
for(ITree child5 : child4) {
size++;
}
}
}
}
}
return size;
Conceptually, keep a stack (LinkedList, etc.). For each child (now, your child loops), add to the stack. Continue looping through the stack until it is finally empty.
This isn't tested, but this should do exactly what you're looking for. I'm just using java.io.File instead of your "ITree", as it's something I can compile against:
int sizeOfTree(File root){
// Start the counter at 1 because the root node counts
int size = 1;
LinkedList<File> stack = new LinkedList<File>();
stack.add(root);
while(!stack.isEmpty()){
File f = stack.remove();
for(File child : f.listFiles()){
size++;
stack.add(child);
}
}
return size;
}
Using a recursive data structure
It is not practically possible to iteratively traverse a recursive data structure, like a tree with pointers - this is because of the fact that the objects "hide" their underlying data elements.
Using a different data structure
All trees can be stored/implemented as to linear, array data structures, where indices can be calculated using exponential mathematics :
For example, a tree [0, 1, 2, 3, null, 4,null] would describe a tree with 0 at the root, where 0 had direct children 1 and 2. And then 1 has left child "3", and 2 has left child "4".
Thus, if you store the tree this way, the number of elements is, naturally, the number of non-null elements in the array.
Put more simply : Store the tree in a linear structure , and you can know the length at any given time without having to make any kind of fancy algorithm.
The key word for your task is recursion. Tree is a classical recursive structure, so you should write recursive method that accepts root nodes, counts size of this node and then calls itself for all children. Here is pseudo code:
public int getSize(ITree root) {
return getSize(root, 0);
}
private int getSize(ITree node, int size) {
size++;
for(ITree child : node.children()) {
size += getSize(child, size)
}
return size;
}
Related
Pseudocode
Created a class that will hold the node and its horizontal height
Using BFS, so create a queue and inserted the first node having a horizontal height of 0
Popped the element from the queue, if the horizontal height doesn't exist in the map then created an entry for it
get the ArrayList of horizontal height and add the value of the node to it
check for the left and right child, if they are not null then add them to the queue
class Solution {
class Node{
TreeNode key;
int h;
Node(TreeNode key,int h){
this.key=key;
this.h=h;
}
}
public List<List<Integer>> verticalTraversal(TreeNode root) {
if(root==null)
return null;
TreeMap<Integer, ArrayList<Integer>> map = new TreeMap<>();
Queue<Node> q=new LinkedList<>();
q.add(new Node(root,0));
while(!q.isEmpty()){
Node tmp=q.poll();
if(!map.containsKey(tmp.h))
map.put(tmp.h,new ArrayList<Integer>());
map.get(tmp.h).add(tmp.key.val);
if(tmp.key.left!=null)
q.add(new Node(tmp.key.left,tmp.h-1));
if(tmp.key.right!=null)
q.add(new Node(tmp.key.right,tmp.h+1));
}
List<List<Integer>> ans=new ArrayList<>();
for(ArrayList<Integer> al:map.values()){
ans.add(al);
}
return ans;
}
}
Problem
Failing for input
Input:
[0,2,1,3,null,null,null,4,5,null,7,6,null,10,8,11,9]
First of all you are probably talking about horizontal height not vertical height as your output suggest. Output you got seems to be correct since when making BFS traversal you are first looking on the left element then the right from up to bottom independently on horizontal heights. Left node of the tree level will always be processed sooner (therefore also its child will be sooner added to the queue) so at level 3 (from up to bottom indexing from 0) node with value 7 will be sooner added to the queue for processing then node with value 6. Therefore output seems to be correct in my eyes, can you tell us why your are expecting different output ?
According to this sentence in your task link (https://leetcode.com/problems/vertical-order-traversal-of-a-binary-tree/):
"If two nodes have the same position, then the value of the node that is reported first is the value that is smaller."
It seems that you need to sort your sublists inside resulting list. You can do that with following code:
sortedResult = resultList.stream()
.map(list -> list.stream().sorted().collect(Collectors.toList()))
.collect(Collectors.toList());
I have a graph which stores it's edges using a HashMap as follows :
HashMap<Integer,LinkedList<Node>> adj;
where Node is defined ;
class Node
{
int number;
int weight;
}
eg
0 : <1,55> -> <2,54> //node 0 is connected to node 1 with edge weight 55 and node 2 with edge weight 54
1 : <0,43> -> <2,44> //node 1 is connected to node 0 with edge weight 43 and node 2 with
edge weight 44
I need to get a list of edges in sorted order by weight and I have no clue how to go about it. I am trying to implement Kruskal's MST.
Is it possible to sort the graph I have defined? If not please suggest a better way of storing it.
Let's start by creating an Edge class:
class Edge implements Comparable<Edge> { // Important: must implement Comparable. More on this later
public Node first; // first connected node
public Node second; // second connected node
public int weight; // move edge weight to Edge class
#Override
public int compareTo(Edge e) {
if (weight < e.weight) {
return -1;
} else if (weight > e.weight) {
return 1;
} else {
return 0;
}
}
}
Because the weight variable is in the Edge class, it isn't needed in Node, so you can remove it:
class Node {
public int number;
// add more variables later is you need here
}
Now, for your program (if there isn't a requirement against it), I would define your list like this:
HashMap<Node, List<Edge>> adj; // use any list implementation you want
This will represent the graph like this inside your program (copied from your example):
Node 0: Edge(Node 0, Node 1, 55), Edge(Node 0, Node 2, 54)
Node 1: Edge(Node 1, Node 0, 43), Edge(Node 1, Node 2, 44)
To answer your question, lets find the edges sorted by edge weight:
ArrayList<Edge> sortedEdges = new ArrayList<Edge>();
for (List<Edge> connectedEdges : adj.values()) {
sortedEdges.addAll(connectedEdges);
}
Collections.sort(sortedEdges);
This simply takes all the Edges in adj and puts them all in one list, and then sorts them according to their weight (because we made Edge extend Comparable<Edge>). As per the Javadoc on Collections.sort(), the sort() method uses merge sort, which runs in O(nlog(n)) time:
Implementation note: This implementation is a stable, adaptive, iterative mergesort that requires far fewer than n lg(n) comparisons when the input array is partially sorted, while offering the performance of a traditional mergesort when the input array is randomly ordered.
Getting the list of all Edges by adj.values takes O(n) time (see this), so the total time complexity of getting the list of edges sorted by weight will be O(n) + O(nlog(n)) = O(nlog(n)).
So there you go. I hope this helped :)
If you have the freedom to change the way nodes are represented, I would like to suggest changing it. Currently the Node class really represents an edge (and a node is represented by Integer, i.e., keys to the adj variable.
For example, the following seems more natural:
Set<Node> nodes = new HashSet<>(); // The enclosing class keeps track of all nodes.
// Represents each node.
class Node {
int nodeId = /* ... */;
// The Node class keeps track of its neighbors, sorted by their weights.
SortedMap<Integer,Node> edges = new TreeMap<>(Collections.reverseOrder());
}
Then, whenever you need to do things in the descending order of the weight, you could do something like:
void method(Node node) {
Iterator<Integer> iter = node.edges.keySet().iterator(); // Iterates in descending order.
while(iter.hasNext()) {
int weight = iter.next();
Node neighbor = node.edges.get(weight);
doSomething( /* ... */ );
}
}
Hi I have a tree in which I would like to get paths from the initial (root) node to all leaves.
I found several algortithms that list (all) apths betwenn any given two nodes within a graph (for example this SO question:
Graph Algorithm To Find All Connections Between Two Arbitrary Vertices)
For binary tree there also exists an algorithm
http://techieme.in/print-all-paths-in-a-tree/
but I work on a tree with various branching factors.
Is there any better way of achieving what I want to do than traversing the tree once in order to get all leaves and then run the algorithm above for all leaves combined with the initial node?
I was thinking about implementing simple DFS extended by some additional stack containing all nodes alongt he path to a single leaf and then listing all sentences by looping through these stacks.
ArrayList<GrammarNode> discovered = new ArrayList<GrammarNode>();
Stack<GrammarNode> S = new Stack<GrammarNode>();
while (!S.empty()) {
node = S.pop();
if (!discovered.contains(node)) {
discovered.add(node);
System.out.println(node.getWord.getSpelling().trim());
for (GrammarArc arc : node.getSuccessors()) {
S.push(arc.getGrammarNode());
}
}
}
UPDATE:
The problem of this is that one has alyways go back to the root in order to generate full sentences. So I guess the question is: How to remember the node which was already fully visited (this means where all children nodes were already explored)?
Printing all paths from the root to every leaf would mean to print the entire tree so I'd just use a simple DFS and do the following for each node:
add it to the list/stack
if the node has children, repeat for the children
if the node is a leaf, print the list/stack
pop the node from the list/stack
Example:
A
/ \
B E
/ \ / \
C D F G
The first steps would look like this:
put A on the list -> {A}
put B on the list -> {A,B}
put C on the list -> {A,B,C}
since C is a leaf, print the list (A,B,C)
remove C from the list -> {A,B}
put D on the list -> {A,B,D}
since D is a leaf, print the list (A,B,D)
...
if you know that the graph is indeed a tree (there is only one path to each node), them yes, a simple DFS would be more efficient (at least from a memory usage point of view). Otherwise, you can also use the iterative deepening DFS.
So here's a sample approach. Note that you need an extra visited field in your node structure:
public class TreeNodeExtra {
int val;
TreeNodeExtra left;
TreeNodeExtra right;
boolean visited;
TreeNodeExtra (int v) {
val = v;
visited = false;
}
}
private ArrayList<ArrayList<TreeNodeExtra>> all_path_from_root_to_leaf(TreeNodeExtra root) {
Stack<TreeNodeExtra> st = new Stack<>();
ArrayList<ArrayList<TreeNodeExtra>> res = new ArrayList<>();
st.push(root);
root.visited = true;
while (!st.isEmpty()) {
TreeNodeExtra top = st.peek();
if (top.left != null && !top.left.visited) {
st.push(top.left);
top.left.visited = true;
}
// if left node is null
else {
if (top.right == null && top.left == null) {
// we have a leaf
ArrayList<TreeNodeExtra> tmpList = new ArrayList<>();
for (TreeNodeExtra t : st) {
tmpList.add(t);
}
res.add(tmpList);
st.pop();
}
else if (top.right != null && !top.right.visited) {
st.push(top.right);
top.right.visited = true;
}
else {
st.pop();
}
}
}
return res;
}
A slight modification of DFS (which includes back-tracking) prints all the paths from a given source. In the below example the graph is represented in adjacency list format.
public void mDFS(ArrayList<node> v,int ind,ArrayList<Boolean> visit,ArrayList<node> tillNow){
visit.set(ind,true);
node n = v.get(ind);
int len = n.adj.size();
tillNow.add(n);
int count = 0;
for(node tmp: n.adj){
if( !visit.get(tmp.id) ){
count++;
tmp.pre = ind;
mDFS(v,tmp.id,visit,tillNow); // id gives index of node in v
}
}
if(count == 0){
for(node tmp: tillNow){
System.out.print((tmp.id + 1) + " - ");
}System.out.print("\n");
}
visit.set(ind,false);
tillNow.remove(tillNow.size() - 1);
return;
}
How to get the position of an Element in the childNode list?
e.g.
<a>
<b></b><!-- return 0 -->
<c></c><!-- return 1 -->
</a>
I don't think Element, Node, or NodeList provide a direct way to get this info, but it's easy enough to write your own quick function to do it:
int indexOfNode(Node node) {
int index;
Node sibling;
index = 0;
while ((sibling = node.getPreviousSibling()) != null) {
node = sibling;
++index;
}
return index;
}
I don't think there's a straightforward way other than to repeatedly call getPreviousSibling() until it returns null or iterate through the parent node's child list until you find one that is == to the node you started with.
As an aside, in the document you give in the question the b element is index 1 in its parent's list of children, and the c element is index 3, because there are whitespace-only text nodes in between (one between the opening a and opening b and another between the closing b and opening c).
I have an Array of Strings that are in order A-Z. I was wondering the best way to go about sorting them for a balanced binary search tree. My initial thought is to split the array up into the first half and the second half and then sort them individually.
Shouldn't I be able to use a recursive way to keep splitting it in half to get the next Node for the tree? I just can't wrap my head around it right now and thought I would ask if any one had any ideas. to lead me in the right direction or provide some examples. Thanks!
i am using my own BinaryTree Class and BinaryTreeNode Class.
EDIT:
public class BinaryTree {
private BinaryTreeNode root;
public void insert(String text) {
root = insertNode(root, text);
}
private BinaryTreeNode insertNode(BinaryTreeNode curNode, String text) {
if (curNode == null) {
BinaryTreeNode newNode = new BinaryTreeNode(text);
//newNode.value = text;
return newNode;
} else {
if (text.compareTo(curNode.value) < 0 ) {
//left child
//use of recursion to properly place Node
curNode.left = insertNode(curNode.left, text);
return curNode;
}
else {
//right
//use of recursion to properly place Node
curNode.right = insertNode(curNode.right, text);
return curNode;
}
}
}
public BinaryTreeNode getRoot() {
return root;
}
public void setRoot(BinaryTreeNode root) {
this.root = root;
}
}
would this be considered a Self balancing binary search tree?
Your tree doesn't seem to be self balancing. A self-balancing BST will take steps, after an insertion, or after a number of insertions, to ensure that it is (roughly) balanced.
If you only add the elements once and use the tree just for reads, you have your sorted array and then proceed as follows: select the element in the middle. create a root with it as key, and then recursively add the elements to its left (the smaller elements) as the left subtree of your root, and the elements to its right as the right subtree, respectively. You should end up with a BST that's more or less balanced. Example code:
public class BinaryTree {
/* ... */
//each recursive call receives a pair of bounds for the part of the
//array it has to process: left and right
public static BinaryTreeNode nodeFromSortedArray(String[]a,
int left, int right){
if (right<left) return null;
if (right==left)
return new BinaryTreeNode(a[left]);
int mid = (left+right)/2;
//create node from middle element
BinaryTreeNode n = new BinaryTreeNode(a[mid]);
//recursively add elements to the left as its right subtree
n.left = nodeFromSortedArray(a, left, mid-1);
//recursively add elements to the right as its right subtree
n.right = nodeFromSortedArray(a, mid+1, right);
return n;
}
public static BinaryTree fromSortedArray(String[]a){
BinaryTree bt = new BinaryTree();
bt.setRoot(nodeFromSortedArray(a,0,a.length-1));
return bt;
}
/* ... */
}
However, in this case, you could simply keep your elements in the sorted array, and use binary search to index into it, instead of a tree. The complexity should be the same, O(logn), but you need less references to store the whole thing, and cache performance should be better.
If you need to have a mutable tree, and want to make it efficient, you'd probably need to make it self-balanced, case in which the order in which you add your elements to it doesn't matter.
If you have a binary search tree that is self-balancing it is quite probably counter-productive to pre-sort the array. The algorithm for optimally adding sorted data to a balanced tree is quite different from the algorithm for adding unordered data.
However there is nothing 'self-balancing' about the code you posted. It is just an ordinary binary tree insertion algorithm.