Trees - potatoscript/dsa GitHub Wiki

🧩 What is a Tree?

In computer science, a tree is a hierarchical data structure. Just like your family tree 🏡 shows different generations, a tree in programming organizes data in a branching structure, with one root and multiple children. Each child can have their own children, and this goes on and on.


🧩 Visual Example:

Here’s a basic tree structure:

         Root (Grandparent)
        /         \
   Child 1       Child 2
     /  \         /     \
  Grandchild 1  Grandchild 2 Grandchild 3
  • Root is the starting point (like the grandparent in a family tree).
  • Child 1, Child 2 are like the children of the root (grandparent).
  • Grandchild 1, Grandchild 2, Grandchild 3 are the grandchildren (children of the child nodes).

🌳 Key Parts of a Tree:

  • Root: The topmost node in a tree. It’s the starting point.
  • Node: Each data point in the tree. Nodes are connected by edges.
  • Edge: The line connecting two nodes. It represents the relationship between them.
  • Leaf: A node that has no children, like the leaves of a tree 🌿.
  • Parent: A node that has children (like a parent in a family).
  • Child: A node that is a descendant of another node.
  • Sibling: Nodes that share the same parent (like brothers and sisters).

🧃 Real-World Analogy

Let’s compare it to something we all know: a family tree! 🌳

Imagine a family with generations of family members. The root would be your grandparent (the top of the tree), and the children are their sons or daughters (your parents and aunts/uncles). The grandchildren would be your generation, and so on.

In programming, trees are used to store data in a way that makes it easy to add, search, and delete information!


💻 Example in C#:

Here’s how we can represent a tree in C#:

1. Defining a Tree Node

Each node in a tree has a value and links to its children.

class TreeNode
{
    public string Value;
    public List<TreeNode> Children;

    public TreeNode(string value)
    {
        Value = value;
        Children = new List<TreeNode>();
    }
}

2. Building a Simple Tree

Let’s build a simple tree with a root and two children:

class Program
{
    static void Main()
    {
        // Root of the tree
        TreeNode root = new TreeNode("Grandparent");

        // Children of the root
        TreeNode child1 = new TreeNode("Parent 1");
        TreeNode child2 = new TreeNode("Parent 2");

        // Adding children to root
        root.Children.Add(child1);
        root.Children.Add(child2);

        // Grandchildren
        TreeNode grandchild1 = new TreeNode("Child 1");
        TreeNode grandchild2 = new TreeNode("Child 2");

        // Adding grandchildren to Parent 1
        child1.Children.Add(grandchild1);
        child1.Children.Add(grandchild2);

        // Printing tree structure
        Console.WriteLine(root.Value); // Grandparent
        foreach (var child in root.Children)
        {
            Console.WriteLine($"  {child.Value}"); // Parent 1, Parent 2
            foreach (var grandchild in child.Children)
            {
                Console.WriteLine($"    {grandchild.Value}"); // Child 1, Child 2
            }
        }
    }
}

Output:

Grandparent
  Parent 1
    Child 1
    Child 2
  Parent 2

🧠 Types of Trees

There are different types of trees depending on how the data is organized:

1. Binary Tree

A binary tree is a tree where each node has at most two children, often referred to as the left and right child.

Example:

        1
       / \
      2   3
     / \
    4   5

2. Binary Search Tree (BST)

In a Binary Search Tree, for any given node:

  • All values in the left subtree are less than the node’s value.
  • All values in the right subtree are greater than the node’s value.

Example:

        10
       /  \
      5   15
     / \    \
    3   7    20

3. AVL Tree (Self-balancing BST)

An AVL tree is a self-balancing binary search tree where the heights of the left and right subtrees of any node differ by at most one.

4. Heap

A heap is a special type of binary tree that satisfies the heap property:

  • Max-heap: The value of each node is greater than or equal to the values of its children.
  • Min-heap: The value of each node is less than or equal to the values of its children.

💡 Basic Tree Operations

  • Insertion: Add a node to the tree.
    Example: Add a new child to a parent.

  • Traversal: Visit all the nodes in the tree. There are three common ways to do this:

    • Pre-order: Visit the root first, then left, then right.
    • In-order: Visit the left child first, then the root, then right.
    • Post-order: Visit the left and right children first, then the root.
  • Searching: Find a specific node in the tree. Example: Find the child node with a particular name.


🧩 Tree Traversals (With C# Code)

Pre-order Traversal (Root, Left, Right):

void PreOrder(TreeNode node)
{
    if (node == null)
        return;
    Console.WriteLine(node.Value);
    foreach (var child in node.Children)
    {
        PreOrder(child);
    }
}

In-order Traversal (Left, Root, Right) – for Binary Trees:

void InOrder(TreeNode node)
{
    if (node == null)
        return;
    InOrder(node.Left);
    Console.WriteLine(node.Value);
    InOrder(node.Right);
}

Post-order Traversal (Left, Right, Root):

void PostOrder(TreeNode node)
{
    if (node == null)
        return;
    foreach (var child in node.Children)
    {
        PostOrder(child);
    }
    Console.WriteLine(node.Value);
}

🧩 Applications of Trees

  • File Systems: The structure of files and directories is often represented using trees.
  • Web Crawlers: Crawlers use trees to explore and index websites.
  • Decision Trees: Used in machine learning to make decisions.
  • Game Trees: Represent possible moves in games (like chess).
  • Expression Parsing: Trees are used to parse and evaluate mathematical expressions.

🚨 Pitfalls to Avoid

  • Unbalanced Trees: If a tree becomes unbalanced (e.g., adding nodes in a sorted order), it can degrade into a linked list, leading to slower operations.
  • Memory Usage: Trees can use more memory due to pointers/edges between nodes.

🧠 Time Complexity (Big O)

  • Search: O(log n) for balanced trees, but O(n) for unbalanced trees.
  • Insertion: O(log n) for balanced trees, but O(n) for unbalanced trees.
  • Deletion: O(log n) for balanced trees, but O(n) for unbalanced trees.
  • Traversal: O(n) – Visit every node once.

🧩 Summary

Trees organize data in a hierarchical structure, making it easy to search, add, and delete data.
Binary Trees have two children per node.
Binary Search Trees store data in a sorted way.
Tree Operations like insert, search, and traversal are crucial.
Big O for trees is O(log n) for balanced trees, and O(n) for unbalanced trees.


⚠️ **GitHub.com Fallback** ⚠️