Create a full and complete binary tree recursively - java

Purpose:
I would like to create a full and complete binary tree, which saves a String value in its leaves, recursively.
Example 1:
Let's say you want to save two Strings in your tree. So you will need a root and two leaves.
* <- root node
/ \
v0 v1 <- leaves
Example 2:
Let's say you want to save three Strings in your tree. So you will need a root, two inner Nodes but four leaves, so the tree is still complete.
* <- root node
/ \
+ + <- inner node
/ \
/ \
/ \ / \
v0 v1 v2 v3 <- leaves
Math trickery:
Its fairly straightforward to calculate the specs for the binary tree.
Height: ⌈log2 expectedNumOfStrings⌉
double height = Math.log(expectedNumOfStrings) / Math.log(2);
int roundedHeight = (int) Math.ceil(height);
Number of leaves: 2Height
int numOfLeaves = (int) Math.pow(2, roundedHeight);
Number of inner Nodes: 2h − 1
int numOfInnerNodes = (int) (Math.pow(2, roundedHeight)-1)
Implementation:
Let's implement a couple of classes for this binary tree. We'll need a BinaryTree class.
/**
* Create a complete binary tree recursively depending on the expected leaves.
*/
public class BinaryTree {
private InnerNode root;
private LeafNode current;
public BinaryTree(int expectedNumOfStrings) {
//sets root node
this.root = new InnerNode();
//set inner nodes
root.createInnerNodes(expectedNumOfStrings);
//set leaves
root.createLeaves(expectedNumOfStrings);
//The way things are now the tree isn't created in one go.
//I'll have to traverse it again for the leaves.
}
}
All elements of the tree share a link to the parent (for the root it's null). Let's create a class TreeNode:
public class TreeNode {
private TreeNode parent;
}
Now let's create InnerNode and LeafNode which just extends TreeNode.
public class InnerNode extends TreeNode {
private BinaryTree left;
private BinaryTree right;
//used to set the root node
public InnerNode() {
super.parent = null;
this.left=null;
this.right=null;
}
public InnerNode(InnerNode parent) {
super.parent= parent;
}
public TreeNode createInnerNodes(int expectedValues) {
//recursive magic happens here. But how?
}
}
and
public class LeafNode extends TreeNode {
private String data;
public LeafNode(InnerNode parent) {
super.parent= parent;
}
public LeafNode createLeaves(int numOfLeaves) {
//recursive magic happens here again. But how?
}
}
Questions and Problems
I want to keep the classes as separated as they are and I want to set the Tree up in one go. How to I set up InnerNodes and Leaves at the "same" time?
InnerNode left and InnerNode right are private so I can only access them from within InnerNode. But how do I deal with the leaves then? Can I just pass the root Node though to InnerNode/Leaves in a method?
What is best used for the recursion? Height or Number of corresponding nodes? Or something else entirely?
How do you set the left and right pointer? I mean the objects to which they point don't exist yet, do they?
Am I on the right track? /o\

Related

Create a binary tree from a sorted array list

I need to program a Huffman compression for Text for an university assignment.
The exercise is split in to multiple points, and one of them is to create a binary tree from a given sorted arrayList which is of type TreeNode, this class looks like this (I removed the method boddies):
public class TreeNode implements Comparable<TreeNode>, Serializable {
private byte value;
private int frequency;
private TreeNode left, right;
/** Creates new TreeNode .. must get initialized with value */
public TreeNode(byte value) {
this(value, 0, null, null);
}
/** Creates new TreeNode with full init */
public TreeNode(byte value, int frequency, TreeNode left, TreeNode right) {
this.value = value;
this.frequency = frequency;
this.left = left;
this.right = right;
public void incFrequency()
public int getFreq()
public Byte getValue()
public TreeNode getLeft()
public TreeNode getRight()
public boolean isLeaf()
public int getSubTreeSize()
public void toHeap(byte[] heap, int myIndex)
public void initLookup(long myCode, int myDepth, Map<Byte, BitCode> lookupTable)
#Override
public int compareTo(TreeNode o)
#Override
public String toString()
public void printSubTree(PrintStream out, int tabs)
public void write(BitStream bs)
public static TreeNode read(BitStream bs)
}
I need to create a binary tree from an arrayList of type TreeNode, the arrayList is sorted by value so I can assume that the element with the smalles value is at index position 0.
The tree has to fulfill one important condition:
The element with the next bigger value needs to be appended on the left, and the element with an even bigger value needs to be appended to the right (the tree will be builded always to the right).
My attemp to approach this problem was to iterate over the list, getting the item, and then appending each item with an odd index to the left leave of the previous node and each item with an even index to the right leave.
Is there a more elegant way to approach this?
(I dont ask you to do the homework for me, but I could need some ideas)
EDIT:
I need to keep the SortedList, since it is a part of the exercise specification
Only for the sake of helping you, you could think along the following lines:
select the middle element as the root node
split the array list into two - left starting from 0 to mid-1, and right starting from mid+1 to last
Recursively repeat step 1 till there is only one element left in the array.
Return that element when only one is left.
Editing my answer as i didn't understand the requirements properly initially.
First Edit -
You could do something like this -
0. If no element, return
1. make first element your root.
2. make next element if it exists as the left child.
3. recursively call the function making its result the right child.
I finally, after some headache, found a solution to this problem.
I iterated over the List of TreeNode,
I removed the first item from the list and stored it in a tempoary variable called "left", I did the same thing again and called that "right" since the list is sorted this will always deliver the biggest and 2nd biggest (in terms of frequency) element of the list.
I added a new TreeNode to the tree, which has as value 0, as frequency the sum of the frequency of the left and left and right TreeNode and a left and right the left and right which were removed from the list in step 2.
I sorted the list again.
These steps where repeated as long as the tree has a size of more than 1 element.
My code looks like this:
private void initializeTree(List tree) {
do{
TreeNode left = tree.remove(0);
TreeNode right = tree.remove(0);
tree.add(new TreeNode((byte)0, left.getFreq() + right.getFreq(), left, right));
Collections.sort(tree);
}while(tree.size() > 1);
root = tree.get(0);
printTree(System.out);
}
The method print tree is a static method if this class which justs prints the tree to the console, the root variable is the root node of the binary tree.

Implementation of DFS using iterative approach in java

I have seen a lot of implementations of DFS using a boolean variable named visited, which I don't wish to use in my code. While considering a scene where we have a Node class that holds the reference to left and right nodes corresponding to its children and data which can be any Object, can this method be applicable to Binary Trees to calculate dfs ? I have a scenario where I don't have a adjacency list or matrix.
Is the following code a good implementation of DFS ? Is the time complexity of the code O(n) ?
public void dfsForTree(BSTNode root) {
Stack<BSTNode> s = new Stack<BSTNode>();
BSTNode node;
if (root == null) {
return;
}
s.push(root);
while (!s.isEmpty()) {
node = s.pop();
System.out.println(node.getData());
if (node != null) {
if (node.getRight() != null) {
s.push(node.getRight);
}
if (node.getLeft != null) {
s.push(node.getLeft);
}
}
}
}
BSTNode class implementation:
public class BSTNode {
private BSTNode left;
private BSTNode right;
private int data;
/* Constructor */
public BSTNode(int n) {
left = null;
right = null;
data = n;
}
/* Function to set left node */
public void setLeft(BSTNode n) {
left = n;
}
/* Function to set right node */
public void setRight(BSTNode n) {
right = n;
}
/* Function to get left node */
public BSTNode getLeft() {
return left;
}
/* Function to get right node */
public BSTNode getRight() {
return right;
}
/* Function to set data to node */
public void setData(int d) {
data = d;
}
/* Function to get data from node */
public int getData() {
return data;
}
A sure tell of an iterative tree walk is it requires an "up" link on a node (or saves them) to be able to backtrack. You do just this - only saving not "up" links but directly next links to go after backtracking. On the other hand, there are no interdependencies between steps. See Is this function recursive even though it doesn't call itself? for how to distinguish iterative and disguised recursive.
Also see Iterative tree walking for an overview of the algorithms.
Now, for computational complexity. The principle can be found at Big O, how do you calculate/approximate it?.
You do:
process every node
exactly once
push & pop nodes from the stack
each node is also pushed and popped exactly once
So, indeed, it's O(N).

How to find a parent of a node in a Binary Tree?

I have a tree that was converted from a general tree to a binary tree:
B
/
A
\
D
/ \
/ I
/ /
C H
\ \
E L
\
G
/
F
that means the following:
B is the root, its children are A, D, I
D's children are C, E, G
I's children are H, L
and so on.
Now, I have to write the following method:
public Position<E> parent(Position<E> v)
Where "v" represents one of the letters in the above tree, and this method needs to find its parent.
I've been struggling with this for hours.. Any ideas?
I'm doing the same homework as you...
For the solution,
A parent in our general tree will be a node in our binary tree that has one left child and that the right child of this parent is not equal to our node v.(see the node I)
You can work on this: if the parent of v as a left child then the parent of v will be the last found node with a left child. But the parent must not have a right child so if it has one, you must search for the upper parent of this last node.(see the node I)
Hope this helps
from what you shown:
algorithm is:
start from root
for every node v
every left-child is node v's child so add this child to node v childs list
every right-child is node v's parent's child(or parent of parent until it is a left-child of its parent, then the node you discovered is the child of left-child node's parent's child).
pseudo code for finding a node's parent in actual tree:
enter node.
if node is left child
print its node->parent.
else
while node->parent is right child
node = node->parent
print node->parent.
This is simple; assuming your Node class does not have access to the parent i.e.
class Node{
Node left;
Node right;
int value;
}
All you need to do is to start from the root and traverse over the tree in a pre-order fashion. If you encounter your target node then its parent is one of the last two elements popped from the Stack (why?)
#See Depth First Search
In this kind of binary tree it's simplest to relabel the child pointers as children (left child) and sibling (right child) because that's what they represent. Since you don't have parent pointers, when you find a node that might be a parent, you must pass it on as you search future nodes.
I need to make lots of assumptions because you gave so little information.
If Position is your node type and your desired function is member of a Tree, then then it will look something like:
private Position<E> parentImpl(Position<E> v, Position<E> node, Position<E> parent) {
if (node.equals(v)) {
return parent;
}
for (Position<E> child = v.children; child != null; child = child.sibling) {
Position<E> rtn = parentImpl(v, child, node); // current node is parent
if (rtn != null) {
return rtn;
}
}
return null;
}
Now the function you want just calls this one.
public Position<E> parent(Position<E> v) {
return parentImpl(v, root, null); // Root has no parent.
}
This will return null both when v is not in the tree at all and when it's the root of the tree.

Binary Tree Creation

I am attempting to create a binary tree from an input of 0's and 1's. For example if the input is 11010010 then the tree that is outputted would have 1 as the root. 2 would be the left child of 1 and 4 would be the right child. 2 would have a right child and it would be 3. That is the end of the tree. As the tree is traversed in preorder, the numbers 1-n (n being the number of 1's in the input) are assigned to the nodes that are visited. A 1 means that the root has children. For example the first 1 means that the root is visited and a 1 is placed as the root. The second 1 means that the root has a left child and a 2 is placed there. The 0 after that means it does not have a left child. The next 1 means that it does have a right child and the 3 is placed there, etc. I am confused on how this tree is created. I understand traversing a tree after it has been created but not how to create a tree by traversing it. Any help would be appreciated.
package tree;
import java.io.*;
public class BinaryTree<ArrayList> implements Serializable
{
private static final long serialVersionUID = 1L;
protected static class Node<ArrayList> implements Serializable
{
private static final long serialVersionUID = 1L;
protected int data;
protected Node<ArrayList> left;
protected Node<ArrayList> right;
public Node(int data)
{
this.data = data;
left = null;
right = null;
}
public boolean isLeft()
{
return (left == null);
}
}
protected Node<ArrayList> root;;
public BinaryTree(int x)
{
Node<ArrayList> node = new Node<ArrayList>(x);
this.root = node;
}
public boolean isLeft()
{
return(root.left == null);
}
public void addLeft(int m, BinaryTree.Node<ArrayList> node)
{
root = new Node<ArrayList>(m);
node.left = root;
}
public void preorder(Node<ArrayList> temp)
{
if (temp!=null)
{
System.out.println(temp.data);
preorder(temp.left);
preorder(temp.right);
}
else
return;
}
}
It sounds like you're constructing a tree in a default, breadth-first manner, assigning values to each node based off of what the string says.
If it helps, first turn the string into an ArrayList<int> of values to put in nodes - For example, 11010010 would become {1, 2, 4, 7}, the indices of each set 1 in the string.
Now, we have to construct the tree - but we'll always construct the tree in the exact same way, called breadth first because you fill shallow levels completely before going deep. We make a node, then tell it 'make your left node, then make your right node, then tell your left node to do this, then tell your right node to do this'. (This is as opposed to depth first, where you make your left node, tell your left node to make nodes, then make your right node and tell your right node to make nodes)
So you'd have a recursive method something like this pseudocode:
void continueTree(ArrayList<int> numbers)
{
if (numbers.count() == 0) return;
this.left = new Node(numbers.get(0));
numbers.remove(0);
if (numbers.count() == 0) return;
this.right = new Node(numbers.get(0));
numbers.remove(0);
this.left.continueTree(numbers);
this.right.continueTree(numbers);
}

Skip nodes during binary tree traversal

I need to traverse a binary tree, skipping the children of any node for which a condition is met.
This implements a tree-guided clustering approach; the leaves of a subtree are considered a cluster when they collectively meet the condition.
It seems like the place to start would be pre-order traversal, but I'm not sure how to modify the algorithm to skip all the children of the current node.
Update
In addition to the two (correct) answers below, one can use the following Java libraries:
MyArch TreeIter - Generic (with adapter class) tree traversal, with child skipping and dynamic maximum traversal depth
Phylosoft Forester - Tree implementation with getAllExternalDescendants and a Newick-to-XML converter
If by skipping all the children you mean not just direct descendants but their entire subtrees, you can do the following:
public void traverse(Node n){
if (n==null)
return;
doSomethingWith(n);
if (!conditionIsMet(n)){
traverse(n.left);
traverse(n.right);
}
}
the first part is easy:
class Tree {
Tree(int data) {
this.data = data;
}
Tree left, right;
Object object;
int data;
}
public class Main {
static void myPreorder(Tree tree) {
if (tree == null) return;
if (tree.data > 2) {
System.out.println("skipping " + tree.data);
return;
}
System.out.println("visiting " + tree.data);
myPreorder(tree.left);
myPreorder(tree.right);
}
public static void main(String[] args) {
Tree root = new Tree(1);
root.left = new Tree(2);
root.right = new Tree(3);
root.right.left = new Tree(4);
root.right.right = new Tree(5);
myPreorder(root);
}
}
the second part: " ... the leaves of a subtree are considered a cluster when they collectively meet the condition. ..." is hard. you would need to examine all of the leaves of a node to see that they met the skip condition.

Categories

Resources