A0A Lecture5U
A0A Lecture5U
A Binary Search Tree (BST) is a binary tree data structure where each node has at
most two child nodes, referred to as the left child and the right child. In a BST,
nodes are organized in a way that satisfies the binary search property:
All nodes in the left subtree of a node have values less than or equal to the
node's value.
All nodes in the right subtree of a node have values greater than or equal to
the node's value.
This property ensures that the BST is a sorted data structure, making it efficient
for searching, insertion, and deletion operations. The binary search tree is
typically used to maintain a collection of elements (e.g., numbers, keys) in a way
that allows for fast retrieval and modification. In fact, binary search trees are
designed to facilitate efficient searching, and the binary search algorithm aligns
well with the structure and properties of a BST.
2 5 8 12 16 23 38 56 72 91
If u want to search 16 which lies at index 4, u need one comparison and will find it
at root node.
If u want to search 72 which lies at index 8, it will require 3 comparisons to find
72.
Binary Search
4 8 10 15 18 21 24 27 29 33 34 37 39 41 43
i=0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
{
mid= floor ( low + high /2 )
If (key==A[mid])
return mid;
else If ( key < A[mid])
high= mid -1
else ( key > A[mid])
low= mid +1
}
return -1;
4 8 10 15 18 21 24 27 29 33 34 37 39 41 43
i=0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
L M H
Mid element 27 is at index 7, and will require one comparison to search. Search will terminate after one
comparison, if we want to search 27.
27
4 8 10 15 18 21 24 27 29 33 34 37 39 41 43
i=0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
L M h
Next, we are searching an element on right hand side,
4 8 10 15 18 21 24 27 29 33 34 37 39 41 43
i=0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
L M H
27
3
11
15 37
27 will be found in one comparison, if we want to search 37, 37> 27(mid), go to right hand side, the new
mid-on RHS is 37, it will take two comparisons.
Take the list on LHS, and its mid is index 3, value 15. And take list on RHS and its mid
4 8 10 15 18 21 24 27 29 33 34 37 39 41 43
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
L M h L M H
M M M M
Level 1 elements require 1 comparison, while level 2 elements require 2 comparisons to search.
Whether an element lie at first location or last location, at most 4 comparisons are required to search or
reach an element in the list. The number of comparisons depends on height of binary tree. The time
taken depends on number of comparisons and number of comparisons are at most logn. So the time
taken for searching in binary search is logn.
1 comparison
2 comparison
3 comparison
4 comparison
Here the worst case time complexity means that the maximum comparisons required to
search an element using binary search are logN.
Successful search
Best Case: Minimum time of binary search= O(1)
Worst Case: Maximum time of binary search= O(logN)
The leftmost blank node indicates unsuccessful search (search will terminate at these
nodes)and represent all those elements that are less than 4 and are not present in the
list. The second leftmost node represent all those elements that are between 4 and 8,
but they are not present in the list. The time taken in Unsuccessful search is always
O(logN).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
3 6 8 12 14 17 25 29 31 36 42 47 53 55 62
} Binary search is calling by dividing the problem into half either on LHS or RHS
}
Binary search will execute recursively either for left half or right half
Refer to the previous binary tree, recursive procedure behaves in the same way in the binary tree. The
maximum no. of comparison it makes is the no. maximum calls it is making. And no.of max calls are
atmost 4. The no. of calls in the recursive algorithm (RA) depends on the height of binary tree i.e logn. If
an element is not found, the RA will make a fifth call to terminate. The time complexity for both iterative
and recursive procedure for binary search is logn.
Recursive algorithm for binary search is a divide and conquer algorithm, and its running time can be
found using recurrence relation, lets us form a recurrence relation for binary search algo using divide
and conquer strategy
If we solve this recurrence relation, we will get time complexity= O(log 2n)
Control Flow:
Iterative: In an iterative procedure, a loop or a sequence of statements is used to
repeat a set of instructions until a certain condition is met. Control is explicitly
managed by looping constructs like "for" or "while" loops.
Recursive: In a recursive procedure, a function calls itself, and control is managed
by these recursive function calls. The function breaks a problem down into
smaller subproblems, and the same function is called with these smaller
subproblems until a base case is reached.
Code Clarity:
Iterative: Iterative procedures are often more straightforward to understand for
many people because they follow a linear sequence of steps. They are well-suited
for problems that can be naturally expressed as a loop.
Recursive: Recursive procedures can be elegant and concise for certain problems
that have a recursive structure. However, they can be less intuitive for some
programmers, and deeply nested recursive calls can make code harder to read.
Resource Usage:
Iterative: Iterative procedures usually require less memory because they do not
involve the overhead of function call stacks. They are often more memory-
efficient.
Recursive: Recursive procedures can consume more memory due to the function
call stack, which is used to keep track of each recursive call. Excessive recursion
can lead to a stack overflow if not managed properly.
Performance:
Iterative: In many cases, iterative procedures can be more efficient in terms of
execution speed because they avoid the function call overhead.
Recursive: Recursive procedures can introduce some overhead due to the
function calls, which may impact performance, especially for deeply nested
recursions. However, some problems are naturally suited to recursive solutions.
Base Cases:
Iterative: In an iterative procedure, you often need to explicitly define the loop
termination condition as part of the loop structure.
Recursive: In a recursive procedure, you need to define a base case, which is the
condition that ends the recursion. Without a base case, a recursive function can
run indefinitely.
Searching and Sorting Algorithms: Many searching and sorting algorithms, like
linear search and bubble sort, are implemented iteratively for their efficiency and
clarity.
Fibonacci Sequence: Computing Fibonacci numbers iteratively is often more
efficient than recursion due to reduced function call overhead.
Factorial Calculation: Calculating the factorial of a number is often done more
efficiently with a loop, especially for large inputs.
Summation: Calculating the sum of an array or a series of numbers is often done
with a loop for its simplicity and efficiency.
Matrix Operations: Matrix multiplication, transposition, and operations are
typically implemented iteratively for speed.
Iterating Through Collections: Tasks involving iterating through arrays, lists, or
other data structures are typically done with loops.
Queue and Stack Operations: Implementing queue and stack data structures and
their operations often involves loops.
Tree Traversal: Recursive procedures are often used for tree traversal, such as in-
order, pre-order, and post-order traversals of binary trees.
Factorial Calculation: Calculating factorials is a classic example of a recursive
problem and is often used to illustrate recursion.
Fibonacci Sequence: Although the iterative approach is more efficient, Fibonacci
sequence generation is often used to demonstrate recursion.
Maze Solving: Solving mazes or puzzles can be a natural fit for recursive
backtracking algorithms.
Towers of Hanoi: Solving the Towers of Hanoi puzzle is a classic example of
recursion.
Graph Traversal: Recursive procedures can be used for graph traversal, such as
depth-first search (DFS).
Binary Search: Binary search can be implemented using recursion, even though
the iterative approach is more efficient.
Merge Sort and Quick Sort: These sorting algorithms are often implemented
using recursion, making them more elegant but less efficient for small datasets.
Recursive Data Structures: Recursive data structures, like linked lists and trees,
naturally lend themselves to recursive procedures for traversal and manipulation.
It's important to note that, in many cases, problems can be solved using both
iterative and recursive approaches, but the choice often depends on factors such
as code clarity, performance requirements, and language constraints.
Extra:
Search Efficiency: Due to the binary search property, searching for an element in a
BST can be done efficiently. Starting from the root node, at each step, the search
algorithm compares the target value with the current node's value and decides
whether to continue the search in the left subtree or the right subtree. This
process eliminates half of the remaining nodes at each step, leading to a time
complexity of O(log n) on average for searching, where n is the number of nodes
in the tree.
Insertion Efficiency: When inserting a new element into a BST, the binary search
property is used to find the appropriate position for the new node. Starting from
the root node, the algorithm compares the value of the new node with the
current node and decides whether to insert it in the left subtree or the right
subtree. This process continues recursively until an appropriate empty position
(leaf node) is found. The time complexity of insertion is also O(log n) on average,
similar to searching, because the height of the tree is balanced in well-
implemented BSTs.
Deletion Efficiency: Deleting a node from a BST involves two main cases:
If the node to be deleted has no children, it can be simply removed from the tree.
If the node has one or two children, the algorithm needs to rearrange the tree
structure while maintaining the binary search property. However, even in this
case, the process involves only rearranging a portion of the tree, and it doesn't
require shifting elements as in arrays. The time complexity for deletion is also
O(log n) on average, where n is the number of nodes in the tree.