Search Tree
Search Tree
The tree is typically used for searching through all possible configurations
or states to find a solution. Examples of problems that use this model
include:
2. Decision Tree:
Root Node: Represents the initial decision point or the feature from
which the tree splits.
Key Differences:
Purpose:
Structure:
Both models have their distinct applications and are essential in different
fields of computer science.
1. Root Node:
2
Search Tree
2. Internal Nodes:
3. Leaf Nodes:
Definition: Nodes at the end of the tree that represent either the
goal state or the final outcome.
State Space Search: These are the terminal states, which might
be goal states or dead-ends in problem-solving.
4. Depth:
Definition: The number of edges from the root to the deepest leaf
node. It indicates the complexity or how deep the search or decision
process might go.
5. Branching Factor:
3
Search Tree
6. Height:
Definition: The number of edges on the longest path from the root
node to any leaf node. The height of the tree defines the worst-case
depth of search or decision-making.
Balanced Tree: A tree where all leaf nodes are at the same depth,
ensuring efficient searches and decision-making. In a balanced state
space search tree, every node explores approximately the same
number of subsequent states.
8. Solution Space:
Pruning:
4
Search Tree
o In Practice:
Heuristic Transformations:
Backtracking:
Pruning:
5
Search Tree
Feature Selection:
Tree Rotation:
Removes
Removes irrelevant branches to
Pruning unpromising
prevent overfitting
branches
6
Search Tree
The height of a search tree refers to the length of the longest path from
the root node to any leaf node, where each path is counted by the number
of edges (or steps) between nodes. In other words, the height represents
the maximum depth of the tree.
Leaf Nodes: The terminal nodes that do not have any children,
representing the end points of paths in the tree.
Formal Definition:
Example:
/ \
B C
7
Search Tree
/\ /\
D E F G
2. Decision Tree:
2. Efficiency Considerations:
8
Search Tree
Summary:
The height of a search tree is the length of the longest path from
the root to a leaf node.
1. Find Operation
The find operation is used to search for a specific value (or node) in the
tree. In a Binary Search Tree (BST), this operation is efficient due to the
ordered structure of the tree.
If the value to be found is less than the current node’s value, move
to the left child.
9
Search Tree
o The value is found (i.e., the current node’s value matches the
target).
o You reach a null child (i.e., the value is not in the tree).
Example:
50
/ \
30 70
/ \ /\
20 40 60 80
Start at 50. Since 30 is less than 50, move to the left child (node
30).
Time Complexity:
Worst case: O(n) if the tree is highly unbalanced (e.g., a linked list).
2. Insert Operation
The insert operation adds a new node to the tree while maintaining the
binary search property. For a Binary Search Tree (BST), all nodes to the
left of a node are smaller, and all nodes to the right are larger.
If the value to insert is less than the current node’s value, move to
the left child.
If the value to insert is greater than the current node’s value, move
to the right child.
Repeat the process until you find a null child (this is where the new
node will be inserted).
10
Search Tree
Example:
50
/ \
30 70
/ \ /\
20 40 60 80
Start at 50. Since 25 is less than 50, move to the left child (node
30).
Since 25 is less than 30, move to the left child (node 20).
50
/ \
30 70
/ \ /\
20 40 60 80
25
Time Complexity:
3. Delete Operation
The delete operation removes a node from the tree. Deleting a node in a
Binary Search Tree (BST) can be complex because the tree structure
must be maintained.
11
Search Tree
Delete the inorder successor (which will be in one of the first two
cases).
Example:
50
/ \
30 70
/ \ /\
20 40 60 80
50
/ \
40 70
/ /\
20 60 80
Time Complexity:
12
Search Tree
Summary of Operations:
Key Points:
In most search trees, such as binary search trees (BST), binary trees,
or other hierarchical structures, traversal is typically done from the root
to the leaf. However, in some cases, you may need to traverse
backwards from a leaf to the root (e.g., to trace a path or apply
operations from a leaf node upwards). Here’s how this process works:
Returning from a leaf to the root means following the parent nodes
upward until you reach the root. This can be done if the tree structure
provides a way to access parent pointers or if you need to track your
path from the root down to a leaf node during a traversal.
13
Search Tree
In many tree structures, each node can store a reference or pointer to its
parent node. This allows you to backtrack from the leaf to the root.
Example:
50
/ \
30 70
/ \ /\
20 40 60 80
In cases where you don’t have parent pointers, you may need to store
the path from the root to the leaf while traversing the tree. A stack can
be used for this purpose.
Step 2: Once the leaf node is reached, the stack will contain the
path from the root to the leaf.
Step 3: By popping elements from the stack, you can return from
the leaf to the root.
Example:
14
Search Tree
In a DFS, you push nodes onto the stack as you go deeper into the tree.
Once a leaf node is reached, you can pop the nodes off the stack to move
back to the root.
When using recursion for tree traversal, the function call stack inherently
keeps track of the path. When the recursive function reaches the leaf
node and begins to return, it will backtrack through the recursive calls,
effectively moving from the leaf to the root.
Step 2: As the recursion proceeds down the tree, the function calls
"push" onto the call stack.
1. Path Tracing:
2. Backtracking Algorithms:
3. Rebalancing a Tree:
4. Updating Values:
15
Search Tree
If you want to trace the path from a leaf node back to the root, for
example, from a node with value 25 in the following BST:
50
/ \
30 70
/ \ /\
20 40 60 80
25
4. Time Complexity
Summary:
The process can be done in O(h) time, where hh is the height of the
tree.
16
Search Tree
When dealing with non-unique keys in a tree, it means that the tree may
allow multiple nodes to have the same value. This situation can arise in a
variety of data structures such as binary search trees (BST), AVL
trees, Red-Black trees, or even tries. When keys are not unique, we
need to handle the insertion, deletion, and search operations in such a
way that multiple nodes with the same key are allowed and the tree
structure remains consistent.
o Common strategies:
Left child values are less than the parent node value.
17
Search Tree
Right child values are greater than the parent node value.
When dealing with non-unique keys, we modify the rule slightly to allow
duplicates:
50
/ \
30 70
/ \
20 40
If you insert a node with value 30 again, you might choose to insert it into
the right subtree (or the left subtree if you prefer).
50
/ \
30 70
/ \
20 40
30
Find operation: In this case, when searching for the key 30, you
would need to follow the tree rules until the key is found. If
duplicates are allowed in the right or left subtrees, you can keep
searching until all occurrences of 30 are found.
Instead of allowing multiple nodes with the same key, you can modify
each node to store an integer counter, which represents how many times
that value appears in the tree.
18
Search Tree
Each node also has a count field, which keeps track of how many
times this key has been inserted.
For example:
50
/ \
30 70
/ \
20 40
50
/ \
30(2) 70
/ \
20 40
The count for node 30 is now 2, indicating that the key 30 appears twice
in the tree. This method keeps the tree structure more balanced and
efficient, as you avoid creating multiple nodes for the same key. However,
it does introduce a small overhead of maintaining the frequency count in
each node.
AVL Trees:
The basic AVL tree properties remain the same (i.e., left child’s value
is smaller, and right child’s value is larger).
Red-Black Trees:
19
Search Tree
Find: The time complexity remains O(log n) for balanced trees (like
AVL or Red-Black trees), even when duplicates are allowed. This is
because the tree structure is maintained, and the search operation
proceeds down the tree similarly to a standard search.
Summary:
20
Search Tree
The chosen strategy affects the tree's structure and the behavior of
operations like insertion, deletion, and searching.
3. Range Queries
6. Path Queries
7. Update Queries
The search operation is the most fundamental query in a tree, where the
goal is to find a node containing a specific key.
If the key to find is less than the current node's key, move to the
left child.
If the key to find is greater than the current node's key, move to
the right child.
If you reach a null child (leaf), the key is not in the tree.
Example:
21
Search Tree
In the tree:
50
/ \
30 70
/ \ /\
20 40 60 80
Start at node 50 (root), since 40 is less than 50, move to the left
child 30.
Since 40 is greater than 30, move to the right child 40, which is the
target.
Perform the search operation to find the node with the key.
Once the node is found, simply return the count stored in that node
(if using a frequency counter).
Example:
For a tree where key 30 appears twice, you may store a node like:
30(2)
This indicates that key 30 appears twice in the tree. You can modify the
insertion logic to update the count when duplicates are inserted.
3. Range Queries
A range query is a query that finds all keys within a certain range (for
example, all keys between x and y). Range queries are efficient in search
trees like BSTs because of their ordered structure.
22
Search Tree
For each node, if its key is within the specified range, it should be
included in the result.
If the node's key is less than the lower bound of the range, skip its
left subtree (as all keys in the left subtree will also be less).
If the node's key is greater than the upper bound of the range, skip
its right subtree.
Example:
50
/ \
30 70
/ \ /\
20 40 60 80
If you want to find keys between 30 and 70, the keys in this range are 30,
40, 50, 60. You would start at the root and only visit subtrees that are
relevant to the range.
Algorithm:
Minimum: Start at the root and keep moving to the left child until
you reach a node with no left child.
Maximum: Start at the root and keep moving to the right child
until you reach a node with no right child.
Example:
50
/ \
30 70
/ \ /\
20 40 60 80
23
Search Tree
The predecessor of a node is the largest key that is smaller than the
current node's key, and the successor is the smallest key that is larger
than the current node's key.
Example:
50
/ \
30 70
/ \ /\
20 40 60 80
6. Path Queries
A path query involves finding a path from a given node to the root or
between two nodes. This is useful in operations like ancestor queries or
finding the Lowest Common Ancestor (LCA).
From node to root: Start at the given node and trace upwards to
the root, visiting each ancestor node.
Between two nodes: To find the path between two nodes, trace
the path from each node to the root, then find their Lowest
24
Search Tree
Common Ancestor (LCA) and trace the paths back down to the
nodes.
7. Update Queries
Update the key: In some trees, you may need to search for a key,
then remove the old key and insert the updated key.
Time Complexity:
Summary:
25
Search Tree
Key Concepts
1. Binary Search Tree (BST): In a basic binary search tree, the keys
are arranged in a way that allows for efficient search (logarithmic
time) in the average case. However, a general BST may not
necessarily be optimal in terms of minimizing the search time for a
set of keys with varying access frequencies.
Problem Formulation
Given:
Each key kik_i has an associated frequency fif_i that indicates how
often the key is accessed.
The goal is to build a binary search tree in which the expected search
cost is minimized. The expected search cost for a key kik_i in the tree is
proportional to its depth in the tree, and the total expected search cost is:
Where:
26
Search Tree
This formula ensures that we calculate the optimal cost for each subtree,
choosing the root that minimizes the expected search cost.
27
Search Tree
4. Final Solution: The final solution, which gives the optimal search
tree for the entire set of keys, is stored in C(1,n)C(1, n), where nn is
the number of keys.
Example
Let’s consider a simple example where we have the following keys and
frequencies:
Frequen
Key
cy
k1k_
34
1
k2k_
8
2
k3k_
50
3
k4k_
19
4
2. Then, use the recursive relation to fill out the cost table C(i,j)C(i, j).
Time Complexity
28
Search Tree
For each pair of nodes ii and jj, we compute the optimal root, which
requires checking each potential root between ii and jj, resulting in
O(n)O(n) work for each pair.
Summary
1. Pre-order Traversal
29
Search Tree
o This means the root is visited first, followed by the left child,
and then the right child.
2. In-order Traversal
3. Post-order Traversal
In a pre-order traversal, the root node is visited first, then the left child,
and finally the right child. If we want to convert a tree into a list using pre-
order traversal, the algorithm would look like this:
Pre-order Algorithm:
Python Example:
class TreeNode:
self.val = key
30
Search Tree
self.left = None
self.right = None
def preorder(root):
result = []
if root:
return result
# Example tree
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
preorder_list = preorder(root)
In-order Algorithm:
31
Search Tree
Python Example:
def inorder(root):
result = []
if root:
return result
inorder_list = inorder(root)
In a post-order traversal, the left and right subtrees are processed first,
and the root node is visited last. This traversal is useful in cases like
evaluating expressions or deleting nodes.
Post-order Algorithm:
Python Example:
def postorder(root):
result = []
if root:
return result
postorder_list = postorder(root)
In level-order traversal, the nodes are visited level by level. This is done
by using a queue to traverse the tree. The root node is processed first,
followed by its children, and then their children, and so on.
Level-order Algorithm:
Python Example:
def level_order(root):
result = []
if not root:
return result
queue = deque([root])
while queue:
node = queue.popleft()
result.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return result
33
Search Tree
level_order_list = level_order(root)
Time Complexity
Summary
Converting trees into lists is a useful operation for many tasks, such as
tree serialization, search optimizations, or just flattening the hierarchical
structure. The traversal order (pre-order, in-order, post-order, or level-
order) determines how the tree is converted into the list, each having
different use cases depending on the desired output.
Removing a tree typically refers to deleting a tree and all of its nodes
from memory. This operation is important in scenarios where you no
longer need a tree structure, such as when clearing a data structure,
deallocating memory, or performing cleanup in applications like game
engines or simulations.
3. Tree Destruction: This ensures that all references to the tree are
cleared, and all nodes are deleted properly.
Steps:
1. Start from the root: Begin at the root node of the tree.
3. Recursively delete the right subtree: Do the same for the right
child and its descendants.
#include <iostream>
class TreeNode {
public:
int val;
TreeNode* left;
TreeNode* right;
35
Search Tree
};
if (root == nullptr) {
return;
deleteTree(root->left);
deleteTree(root->right);
delete root;
int main() {
deleteTree(root);
return 0;
36
Search Tree
In this example:
It starts by deleting the left and right subtrees before deleting the
root node.
class TreeNode:
self.val = value
self.left = None
self.right = None
def delete_tree(root):
if root is None:
return
delete_tree(root.left)
delete_tree(root.right)
root = None
37
Search Tree
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
delete_tree(root)
In this example:
Setting the root to None ensures that Python's garbage collector will
clean up the tree nodes when no references to them remain.
Time Complexity
Considerations
4. Edge Cases:
o If the tree is empty (i.e., the root is None), the function should
simply return without any operations.
38
Search Tree
Summary
Removing a tree means deleting all its nodes and freeing the
memory used by the tree structure.
Key Operations:
39
Search Tree
Example:
Time Complexity:
2. Weight-balanced Trees
Key Operations:
40
Search Tree
Time Complexity:
3. (a, b)-Trees
All leaf nodes are at the same level (height of the tree is balanced).
Key Properties:
Each node (except for the root) must have at least a children and at
most b children.
The root node must have at least 2 children unless it's a leaf.
The number of keys in a node must be at least a-1 and at most b-1.
Operations:
Deletion: If a node has too few keys after deletion (fewer than a-1),
it is merged with its sibling or a key is borrowed from a sibling node.
Time Complexity:
4. B-Trees
41
Search Tree
Key Properties:
Degree of the tree: Each node can store between t-1 and 2t-1
keys, where t is the minimum degree of the tree.
All leaf nodes are at the same level, ensuring a balanced structure.
Operations:
Time Complexity:
Number
Balancing Operati
Tree Type of Keys Use Cases
Criterion ons
per Node
General-purpose
Height- Height difference
search trees, e.g., for
balanced between left and 1 O(log n)
in-memory data
(AVL) right subtrees
structures
General-purpose
Number of nodes
Weight- search trees, focusing
(weight) in 1 O(log n)
balanced on balancing based on
subtrees
weight
42
Search Tree
Number
Balancing Operati
Tree Type of Keys Use Cases
Criterion ons
per Node
Conclusion
Red-Black Trees
5. Leaf Nodes are Black: The leaf nodes (NULL nodes) are
considered black.
These properties ensure that the tree remains balanced, which in turn
guarantees that the height of the tree is logarithmic relative to the
number of nodes in the tree.
43
Search Tree
The number of black nodes on any path from the root to a leaf is
consistent, and the tree’s height is limited due to the alternating
black and red nodes. In the worst case, the height is twice the
black-height of the tree.
Insertion and deletion in a Red-Black Tree are done in such a way that the
tree remains balanced after each operation. After each insertion or
deletion, the tree may become unbalanced, and several rotations (left or
right) along with color changes are used to restore balance.
Time Complexity:
44
Search Tree
Red-Black Trees allow a bit more flexibility than AVL trees (with
balance factors of -2, -1, 0, 1, and 2), but they still maintain the
height within O(log n), making them close to optimal in terms of
height.
In the case of red-black trees, while the balance is not as strict as AVL
trees, the constraints on node color and structure still ensure that the
height of the tree is logarithmic, keeping it close to optimal.
Insertion
O(log n) with rotations and color
Complexit O(log n) with rotations
changes
y
Deletion
O(log n) with rotations and color
Complexit O(log n) with rotations
changes
y
Space
Complexit O(n) O(n)
y
45
Search Tree
Summary
Both types of trees are used in different scenarios based on the need for
stricter balance (AVL) or more flexible balancing (Red-Black).
46
Search Tree
1. Normal Binary Search Tree (BST) Insertion: Insert the new node
in the appropriate position (as in a regular binary search tree),
ensuring that the binary search property is maintained.
1. Insert the Node: Insert the new node as a red node (by default).
This is the first step in maintaining the property that newly inserted
nodes are always red.
1. Initial Conditions: Start with the root of the tree. The root is
always black, so we do not have to worry about it being red.
o If the parent node of the newly inserted node is red (i.e., the
violation of consecutive red nodes occurs), we perform a
recoloring or rotation to fix this violation.
o If the parent and the uncle of the newly inserted node are
both red, we perform a recoloring operation:
47
Search Tree
Suppose we are inserting a node into a red-black tree, and the parent
node is red, which causes a violation. Here’s how top-down balancing
works:
2. Parent and Uncle are Red: If the parent and uncle are both red,
we perform recoloring. This involves changing the parent and uncle
48
Search Tree
3. Parent is Red, Uncle is Black: If the parent is red and the uncle is
black or NULL, we perform the necessary rotations to restore
balance.
Top-Down Red-
Property Bottom-Up Red-Balancing
Balancing
Summary
49
Search Tree
rotations and recoloring during the insertion process itself, rather than
after the node has been inserted. This can result in fewer rotations and
more efficient balancing, especially when handling violations of the red-
red property or black-height consistency.
50