Professional Documents
Culture Documents
Binary Tree
Binary Tree Data Structure
A binary tree organizes data in a hierarchical structure, similar to how you might
organize files in a file folder. The top node in a binary tree is called the root, and it
can have two child nodes (left and right). Each of those child nodes can also have its
child nodes, and so on.
For example, imagine you are creating a family tree. The root node would represent
the oldest generation (e.g., great-grandparents). The left child node would represent
the father, and the right child node would represent the mother. Each child node can
have its child nodes, representing the next generation (e.g., grandparents). And so
on, until you reach the leaf nodes, representing the youngest generation (e.g., you).
Why use Tree Data Structure?
Trees are a functional data structure because they allow for efficient organization
and manipulation of data. In addition, trees have a hierarchical structure, which
means that data can be organized in a way that makes it easy to find, sort, and
search for specific information.
For example, a binary search tree can be used to quickly find a specific value
because it's organized so that each node's value is higher than the values of the
others. Of all the nodes in its left subtree and less than the values of all the nodes in
its right subtree. This means you can eliminate half of the tree from your search with
each comparison you make.
In addition, trees can represent data in a way that mirrors real-world relationships
and hierarchies. For example, a family tree can represent the relationships between
family members, or an organizational chart can represent the hierarchy within a
company.
A pointer typically represents a binary tree's topmost node, also known as the tree's
root. The root node contains a value and pointers to its left and right child nodes.
Each child node can also have its child nodes, creating a hierarchical structure that
forms the binary tree. This pointer-based representation allows for efficient tree
traversals, insertions, and deletions.
Basic Operation On Binary Tree:
1. Traversal: visiting each node in the tree in a specific order, such as in-order,
pre-order, or post-order.
2. Insertion: adding a new node to the tree.
3. Deletion: removing a node from the tree.
4. Searching: finding a specific node in the tree based on its value.
5. Finding the Minimum and Maximum value: finding the node with the smallest
or largest value in the tree.
6. Finding the Height: Calculate a number of edges present between the root
and the farthest leaf node.
7. Finding the Depth: calculating the number of edges from the root to a specific
node.
1. Balancing: ensuring that the tree is balanced can improve the performance of
some operations.
2. Copy: creating a new tree that is identical to an existing tree
3. Compare: comparing two trees to check if they are identical
4. Inversion: creating a new tree with the left and right subtrees of the original
tree are swapped
5. Serialization and Deserialization: converting a tree to a string or a byte stream
representation for storage or transmission and vice-versa
1. File systems for organizing and managing files on a computer's hard drive
2. Database indexing for faster searching and sorting
3. Network routing to find the best path between two nodes
4. Game development for determining visibility, collision, and lighting
5. Data compression using Huffman coding
6. Artificial Intelligence using decision trees and random forests
7. Natural Language Processing using decision trees for parsing, semantic
analysis, and machine translation.
1. In-order traversal: visits the left subtree, the root node, and the right subtree.
This results in visiting the nodes in ascending order for a binary search tree.
2. Pre-order traversal: visits the root node, left, and right subtree. This is often
used to create a copy of the tree or to get a prefix expression of an expression
tree.
3. Post-order traversal: visits the left subtree, then the right subtree, and finally,
the root node. This is often used to delete the tree or to get a postfix
expression of an expression tree.
These three traversals are called DFS traversals, using the DFS algorithm to
traverse the tree. The DFS algorithm goes deep into the tree as much as possible
before backtracking.
1. Level-order traversal: This algorithm visits all the nodes of the tree level by
level, from left to right. It uses a queue data structure to keep track of the
following nodes to visit. It is also known as Breadth-First Search (BFS)
The BFS algorithm is mainly used for tasks such as finding the shortest path
between two nodes or searching for a specific node in the tree. Because it visits all
the nodes at each level before moving on to the next level, it is guaranteed to find
the shortest path if one exists.
In this example, a root node is created with a value of 10, and left and right child
nodes are added with values of 5 and 15, respectively. Then the left child of a left
child is added with value 2, and the left child of the right child is added with value 7.
Properties of Binary Tree
2. Degenerate Binary Tree: A binary tree in which every internal node has one
child.
3. Skewed Binary Trees: A binary tree in which all the nodes are either
left-skewed or right-skewed, meaning that the tree is either entirely
left-leaning or entirely right-leaning.
These are the most common binary trees based on the number of children. Each of
these types has its unique properties and use cases and is used in different
situations based on the problem.
1. Binary Search Tree (BST): A binary tree in which the value of each node is
greater than or equal to its left child and less than or equal to its right child.
This type of tree is often used for searching, sorting, and other operations that
require quick access to elements based on their values.
2. AVL Tree: A balanced binary search tree that maintains balance by rotating
nodes.
3. Red-Black Tree: A balanced binary search tree that maintains balance by
coloring nodes.
4. B-Tree: A self-balancing tree that allows for efficient insertion, deletion, and
searches operations on large data sets.
5. B+ Tree: A variation of the B-Tree optimized for operations such as insertion,
deletion, and search on large data sets and is commonly used in databases
and file systems.
6. Segment Tree: A specialised tree data structure used to query and update
ranges of values efficiently. It is often used for operations such as range sum,
range min/max, and range count in dynamic arrays.
Advantages of Binary Tree:
1. Efficiency: Binary trees can quickly search, insert, and delete elements,
making them a popular choice for data structures such as search trees and
priority queues.
2. Flexibility: Binary trees can represent various data structures, such as lists,
stacks, queues, and more.
3. Space efficiency: Binary trees can represent large data sets using a smaller
amount of memory than other data structures.
4. Easy to understand: The structure of a binary tree is relatively simple, making
it easy to understand and implement.
5. Easy to Traverse: Binary trees are easy to traverse, and the traversal can be
done in various ways, like in-order, pre-order, post-order, and level-order
traversals.
6. Can be balanced: Binary trees can be balanced, which can help keep the
tree's height as small as possible and improve the efficiency of operations.
7. Applications: Binary trees have a lot of applications in computer science. They
can be used in algorithms such as Huffman coding, Trie, and many more.
Disadvantages of Binary Tree:
In this example, a BinaryTree class is defined, which has three data members, left
and right. Then, in the binary_tree_using_array function, the array is passed as an
argument, and each node's left and right children are assigned by recursively calling
the function with the appropriate array indices.
The function starts from the root, which is the first element of the array. For each
element in the array, it creates a new BinaryTree object, assigns the value of the
current element to it, and recursively calls the function for the left and right children
using the appropriate array indices.
A Binary Search Tree (BST) is a binary tree in which the value of each node is
greater than or equal to its left child and less than or equal to its right child. This
property makes it easy to find specific elements in the tree quickly by comparing the
value of each node.
Imagine a tree where each node represents a number, and each branch represents
a comparison. To find a specific number, you start at the tree's root and compare the
number to the value of the root. If the number is smaller, you go to the left branch; if
it is more extensive, you go to the right branch. Repeat this process until you find the
number or reach a leaf node.
This type of tree is often used for searching, sorting, and other operations that
require quick access to elements based on their values. It is called a "search tree"
because it allows for efficient searching of elements in the tree.
It is important to note that this is a balanced tree, and the tree may not remain
balanced after insertions and deletions; we have different types of balanced binary
search trees, such as AVL, Red Black Tree, and others.
These properties make the BST a functional data structure for operations that
require quick access to elements based on their values, such as searching, sorting,
and other functions.
Handling approach for Duplicate values in the Binary Search tree:
There are different approaches to handling duplicate values in a Binary Search Tree
(BST) depending on the specific requirements of the application
1. Ignore duplicate values
2. Store duplicate values in the same node
3. Store duplicate values in a separate node
4. Store duplicate values in the node's left or right child with the original value.
Several operations can be performed on a Binary Search Tree (BST). Here are a few
common ones:
Inserting a new node into a Binary Search Tree (BST) involves finding the
appropriate position for the new node based on its value and then creating and
linking the new node to the existing tree.
In this example, a Node class is defined, which has three data members, data left
and right. The insert function takes the root of the BST and the value to be inserted
as parameters.
The function starts by checking if the root is None, in which case it creates a new
node with the given value and returns it. Otherwise, it compares the value of the new
node to the value of the current node. If the new value is less than the current value,
it recursively calls the insert function on the left child. If the new value is greater than
the current value, it recursively calls the insert function on the right child. This
process continues until it reaches a leaf node, where it creates a new node and
attaches it to the appropriate child of the leaf node.
Inorder traversal:
An in-order traversal of a Binary Search Tree (BST) visits the tree nodes in the order
of the left, root, and right child.
This example defines a node class with three data members, left and right. The in
order function takes the root of the BST as a parameter and recursively visits the left
subtree, the root, and the right subtree.
The function starts by checking if the root is None, in which case it returns.
Otherwise, it recursively calls the inorder function on the left child. Then it prints the
current node's data and recursively calls the inorder function on the right child.
This process continues until all the tree nodes are visited, and the data of each node
is printed in the order of the left child, root, and right child.
Preorder traversal:
Preorder traversal of a Binary Search Tree (BST) visits the tree's root first, then the
left, and finally the right.
In this example, a Node class is defined, which has three data members, data left
and right. The preorder function takes the root of the BST as a parameter and
recursively visits the root, left subtree, and right subtree.
The function starts by checking if the root is None, in which case it returns.
Otherwise, it prints the current node's data, then recursively calls the preorder
function on the left child, and finally, it recursively calls the preorder function on the
right child.
This process continues until all the tree nodes are visited, and the data of each node
is printed in the order of root, left child, and right child.
Postorder traversal:
Postorder traversal of a Binary Search Tree (BST) visits the left subtree first, then the
right subtree, and finally, the tree's root.
In this example, a Node class is defined, which has three data members, data left
and right. The postorder function takes the root of the BST as a parameter and
recursively visits the left subtree, then the right subtree, and finally, the tree's root.
The function starts by checking if the root is None, in which case it returns.
Otherwise, it recursively calls the postorder function on the left child, then on the
right child, and finally, it prints the current node's data.
This process continues until all the tree nodes are visited, and the data of each node
is printed in the order of the left child, right child, and root.
Level order traversal:
Level-order traversal of a Binary Search Tree (BST) visits the nodes of the tree level
by level, from top to bottom.
In this example, a Node class is defined, which has three data members, data left
and right. The level order function takes the root of the BST as a parameter and
visits the nodes of the tree level by level.
The function uses a queue to keep track of the nodes to be visited at each level. It
starts by adding the root to the queue and then enters a while loop. In each iteration,
it prints the node's data at the front of the queue and then removes it from the queue.
It then adds the left and right children of the node to the queue if they exist.
This process continues until all the tree nodes are visited in level order.
Print nodes at given Level :
You can use a level-order traversal approach to print all the nodes at a given level in
a Binary Search Tree (BST).
In this example, a Node class is defined, which has three data members, data left
and right. The printGivenLevel function takes the root of the BST and the level to be
printed as parameters. It starts by checking if the root is None, in which case it
returns. If the level is 1, it prints the current node's data. If the level is greater than 1,
it recursively calls the printGivenLevel function on the left and right children, with a
level decremented by 1.
The getHeight function takes the root of the BST as a parameter and returns the
tree's height. The printLevelOrder function takes the root of the BST as a parameter
and calls the printGivenLevel function for each level of the tree, starting from 1 to the
height of the tree.
The function starts by checking if the root is None, in which case it returns.
Otherwise, it checks if the root node is a leaf node (i.e., it has no left or right children)
by checking if 'root.left' and 'root.right' is None. If the root node is a leaf node, it prints
the data of the root node. Then it recursively calls the printLeafNodes function on the
left and right children.
This process continues until all the tree leaf nodes are visited, and their data is
printed.
In this example, a Node class is defined, which has three data members, data left
and right. The printNonLeafNodes function takes the root of the BST as a parameter
and recursively visits the left and right subtrees of the tree.
The function starts by checking if the root is None, in which case it returns.
Otherwise, it checks if the root node is a non-leaf node (i.e., it has left or right
children) by checking if root.left or root.right is None. If the root node is a non-leaf
node, it prints the data of the root node. Then it recursively calls the
printNonLeafNodes function on the left and right children.
This process continues until all the non-leaf nodes of the tree are visited, and their
data is printed.
In this example, a Node class is defined, which has three data members, data left
and right. The printRightView function takes the root of the BST, the current level of
the node, and a list of max_level as parameters. The function first checks if the root
is None, in which case it returns.
Otherwise, it checks if the current level is greater than the max_level. If it is, it prints
the data of the root node and updates the max_level. Then it recursively calls the
printRightView function on the right child first, followed by the left child, with the level
incremented by 1.
The rightView function takes the root of the BST as a parameter and calls the
printRightView function with level 1 and max_level set to 0.
This process continues until all the tree nodes are visited, and the correct view of the
tree is printed.
In this example, a Node class is defined, which has three data members, data left
and right. The printLeftView function takes the root of the BST, the current level of
the node, and a list of max_level as parameters. The function first checks if the root
is None, in which case it returns.
Otherwise, it checks if the current level is greater than the max_level. If it is, it prints
the data of the root node and updates the max_level. Then it recursively calls the
printLeftView function on the left child first, followed by the right child, with the level
incremented by 1.
The leftView function takes the root of the BST as a parameter and calls the
printLeftView function with level 1 and max_level set to 0.
This process continues until all the tree nodes are visited and the left view of the tree
is printed.
Height of BST:
The height of a Binary Search Tree (BST) is the number of levels in the tree.
In this example, a Node class is defined, which has three data members, data left
and right. The height function takes the root of the BST as a parameter and
recursively visits the left and right subtrees of the tree.
The function starts by checking if the root is None, in which case it returns 0.
Otherwise, it finds the height of the left subtree by calling the height function
recursively on the left child and stores it in the variable left_height. Similarly, it finds
the height of the right subtree and keeps it in the variable right_height.
Then it compares the left_height and right_height and returns the maximum of the
two plus 1 (to account for the current level).
This process continues until all the tree nodes are visited and the tree's height is
returned.
The deleteNode function starts by checking if the root is None, in which case it
returns None. Then it checks if the key to be deleted is less than the root data; it
recursively calls the deleteNode function on the left subtree. If the key is greater than
the root data, it recursively calls the deleteNode function on the right subtree.
If the key is equal to the root data, it checks if the root has no left child or no right
child, in which case it can directly delete the root. If the root has both a left and right
child, it finds the in-order successor of the root and replaces the root data with it,
then recursively calls the deleteNode function on the right subtree.
This process continues until the node with the given key is found and deleted, and
the tree is modified accordingly.
In this example, a Node class is defined, which has three data members, data left
and right. The findMinNode function takes the root of the BST as a parameter,
traverses the tree's left subtree until it reaches a leaf node. Then, the function returns
the data of the leftmost leaf node.
This process continues until all the tree nodes are visited and the total number of
nodes is returned.
Delete a BST:
Deleting a Binary Search Tree (BST) involves removing all the nodes of the tree.
This can be done by traversing the tree in a post-order fashion, which visits the left
and right children before the current node and then frees the memory allocated to
the current node.
In this example, a Node class is defined, which has three data members, data left
and right. The deleteTree function takes the root of the BST as a parameter, and it
recursively visits the left and right subtrees of the tree in a post-order fashion. The
function starts by checking if the root is None, in which case it returns. Otherwise, it
recursively calls the deleteTree function on the left and right children of the current
node, and then it prints the current node's data and deletes it using the del keyword.
This process continues until all the tree nodes are visited, and the tree is deleted.
Applications of BST
Binary Search Trees (BSTs) has many practical applications, some of which include:
1. Sorting: BST can sort a large amount of data efficiently.
2. Searching: BST allows fast searching of elements in a large data set.
3. Dictionary operations: BST can implement dictionary operations like adding,
searching, and deleting words.
4. Data compression: BST can be used for data compression by storing only the
differences between consecutive elements rather than the elements
themselves.
5. File systems: BST can locate files quickly on a hard drive.
6. Graph algorithms: BST can be used in graph algorithms such as Dijkstra's
shortest path algorithm.
7. Game development: BST can be used for AI, physics, and collision detection.
8. Database indexing: BST can be used to speed up queries.
BSTs are efficient data structures with many real-world applications due to their time
and space complexity, making them a good choice for many data-driven
applications.
Binary Search Trees (BSTs) have several advantages, some of which include the
following:
1. Fast Search: BSTs offer O(log n) time complexity for searching an element
much faster than a linear search O(n) in an unsorted array or list.
2. Fast Insertion and Deletion: BSTs offer O(log n) time complexity for inserting
and deleting elements faster than O(n) in an unsorted array or list.
3. Sorted order: BSTs maintain the elements in a sorted order which is helpful for
many applications.
4. Space efficient: BSTs use less memory than an unsorted array or list, as they
only store references to the left and right children.
5. Easy to implement: BSTs are easy to implement and understand, which
makes them a good choice for many data-driven applications.
Binary Search Trees (BSTs) also have some disadvantages, which include the
following:
1. Unbalanced Trees: If the tree becomes unstable, the time complexity of the
search, insertion and deletion operations can degrade to O(n), which is slower
than O(log n) in a balanced tree.
2. Extra Space: In a worst-case scenario, a BST can degenerate into a linked list
and require extra space to store the left and right pointers.
3. The complexity of balancing: Keeping a tree balanced is a complex task, and
different balancing algorithms have advantages and disadvantages.
4. Extra time for balancing: Maintaining a balanced tree takes spare time and
effort, which can add to the program's complexity.
If you're looking to get into Web Development,
then AlmaBetter is the best place to start your
journey.
Link: https://link.almabetter.com/9w63