Skip to content
Asterios Raptis edited this page Sep 13, 2024 · 4 revisions

Example: Creating a Tree Node

You can create a basic tree node by specifying the value and setting children if needed. Below is an example of how to use the BaseTreeNode class:

BaseTreeNode<String, Long> rootNode = new BaseTreeNode<>("Root Node");
BaseTreeNode<String, Long> childNode1 = new BaseTreeNode<>("Child Node 1");
BaseTreeNode<String, Long> childNode2 = new BaseTreeNode<>("Child Node 2");

rootNode.addChild(childNode1);
rootNode.addChild(childNode2);

Explanation:

  • rootNode is the root of the tree, and childNode1 and childNode2 are added as its children.

Example: Traversing the Tree

You can traverse the tree and return all nodes in the tree using the traverse() method:

Collection<BaseTreeNode<String, Long>> allNodes = rootNode.traverse();
for (BaseTreeNode<String, Long> node : allNodes) {
    System.out.println(node.getValue());
}

Explanation:

  • The traverse() method returns a collection of all nodes in the tree, which is then iterated to print the values of each node.

Example: Finding Nodes by Value

You can find all nodes with a specific value using the findAllByValue() method:

Collection<BaseTreeNode<String, Long>> matchingNodes = rootNode.findAllByValue("Child Node 1");
matchingNodes.forEach(node -> System.out.println("Found node: " + node.getValue()));

Explanation:

  • This example searches for all nodes in the tree with the value "Child Node 1" and prints them.

Example: Sorting Children

You can set a comparator to sort the children of a node. For example, sorting nodes alphabetically:

rootNode.setChildComparator(Comparator.comparing(BaseTreeNode::getValue));
rootNode.sortChildren();

Explanation:

  • The children of rootNode are sorted alphabetically based on their values.

Example: Checking Relationships

You can check relationships between nodes, such as whether a node is a child or sibling of another:

boolean isChild = rootNode.isChild(childNode1);
boolean hasParent = childNode1.hasParent();
boolean isRoot = rootNode.isRoot();

Explanation:

  • isChild checks if childNode1 is a child of rootNode.
  • hasParent checks if childNode1 has a parent.
  • isRoot checks if rootNode is the root of the tree.

Example: Moving a Node

You can move a node to a new parent using the move() method:

childNode1.move(childNode2);

Explanation:

  • childNode1 is moved to be a child of childNode2.

Example: Using Expression Tree with BaseTreeNode

Here’s how you can implement an Expression Tree using the BaseTreeNode. This example will demonstrate the construction, traversal, and evaluation of an expression tree for the mathematical expression a + b * c.

Step 1: Create the Expression Tree Structure

We'll represent the expression a + b * c in the form of a tree. The tree structure for this expression looks like this:

      +
     / \
    a   *
       / \
      b   c
  • + is the root node, representing the addition.
  • * is the right child of +, representing multiplication.
  • a, b, and c are the leaf nodes, representing operands.

Step 2: Implementing Expression Tree with ITree or BaseTreeNode

Using the BaseTreeNode class, you can create the nodes of the expression tree.

Code Example:

import io.github.astrapi69.gen.tree.BaseTreeNode;
import java.util.Collection;

public class ExpressionTreeExample {

    public static void main(String[] args) {
        // Create the operand nodes
        BaseTreeNode<String, Long> a = new BaseTreeNode<>("a");
        BaseTreeNode<String, Long> b = new BaseTreeNode<>("b");
        BaseTreeNode<String, Long> c = new BaseTreeNode<>("c");

        // Create the operator nodes
        BaseTreeNode<String, Long> multiply = new BaseTreeNode<>("*");
        BaseTreeNode<String, Long> add = new BaseTreeNode<>("+");

        // Construct the tree by setting the children
        multiply.addChild(b);  // 'b' is the left child of '*'
        multiply.addChild(c);  // 'c' is the right child of '*'
        
        add.addChild(a);  // 'a' is the left child of '+'
        add.addChild(multiply);  // The multiplication result is the right child of '+'

        // Now 'add' is the root of the entire expression tree
        evaluateExpressionTree(add);
        traverseAndPrintInOrder(add);
        traverseAndPrintPostOrder(add);
    }

    // Example of tree traversal in infix order (left, root, right)
    public static void traverseAndPrintInOrder(BaseTreeNode<String, Long> node) {
        if (node == null) return;

        Collection<BaseTreeNode<String, Long>> children = node.getChildren();
        if (children.size() > 0) {
            traverseAndPrintInOrder((BaseTreeNode<String, Long>) children.toArray()[0]); // left child
        }

        // Print the current node's value (operator or operand)
        System.out.print(node.getValue() + " ");

        if (children.size() > 1) {
            traverseAndPrintInOrder((BaseTreeNode<String, Long>) children.toArray()[1]); // right child
        }
    }

    // Example of tree traversal in post-order (left, right, root)
    public static void traverseAndPrintPostOrder(BaseTreeNode<String, Long> node) {
        if (node == null) return;

        Collection<BaseTreeNode<String, Long>> children = node.getChildren();
        if (children.size() > 0) {
            traverseAndPrintPostOrder((BaseTreeNode<String, Long>) children.toArray()[0]); // left child
        }

        if (children.size() > 1) {
            traverseAndPrintPostOrder((BaseTreeNode<String, Long>) children.toArray()[1]); // right child
        }

        // Print the current node's value (operator or operand)
        System.out.print(node.getValue() + " ");
    }

    // Simple method to "evaluate" the tree (in this case, just prints the expression)
    public static void evaluateExpressionTree(BaseTreeNode<String, Long> node) {
        System.out.print("Expression Tree in Infix: ");
        traverseAndPrintInOrder(node); // a + b * c
        System.out.println();
        System.out.print("Expression Tree in Postfix: ");
        traverseAndPrintPostOrder(node); // a b c * +
        System.out.println();
    }
}

Step 3: Explanation

Tree Construction:

  • The operands a, b, and c are represented as leaf nodes.
  • The operator nodes + and * are internal nodes.
  • The root of the tree is the + operator, and its left child is a, while its right child is the result of the multiplication operation (* node).

In-Order Traversal (Infix Expression):

The in-order traversal prints the expression in infix notation: a + b * c. This is achieved by visiting the left child, then the current node, and finally the right child.

Post-Order Traversal (Postfix Expression):

The post-order traversal prints the expression in postfix notation: a b c * +. This traversal visits both children first, then the current node.

Step 4: Running the Code

When you run the code, you’ll get the following output:

Expression Tree in Infix: a + b * c 
Expression Tree in Postfix: a b c * + 

Conclusion:

This example shows how to use the BaseTreeNode class to construct and traverse an expression tree. By representing operators as internal nodes and operands as leaf nodes, you can build and evaluate complex mathematical expressions. You can easily adapt this structure for evaluating arithmetic expressions, performing transformations, or generating different notations (infix, postfix, prefix).