Algorithm Design Unit 2
Algorithm Design Unit 2
UNIT 2
A Binary tree is represented by a pointer to the topmost node (commonly known as the “root”)
of the tree. If the tree is empty, then the value of the root is NULL. Each node of a Binary Tree
contains the following parts:
1. Data
2. Pointer to left child
3. Pointer to right child
Basic Operation On Binary Tree:
Inserting an element.
Removing an element.
Searching for an element.
Traversing the tree.
Auxiliary Operation On Binary Tree:
Finding the height of the tree
Find the level of a node of the tree
Finding the size of the entire tree.
Topic :
Introduction
Basic Operation
Traversals
Standard Problems on Binary Trees
Introduction :
1. Introduction to Binary Tree – Data Structure and Algorithm Tutorials
2. Properties of Binary Tree
3. Types of Binary Tree
4. Applications, Advantages and Disadvantages of Binary Tree
5. Binary Tree (Array implementation)
6. Complete Binary Tree
7. Perfect Binary Tree
Basic Operations on Binary Tree:
1. Tree Traversals (Inorder, Preorder and Postorder)
2. Level Order Tree Traversal
3. Find the Maximum Depth or Height of given Binary Tree
4. Insertion in a Binary Tree
5. Deletion in a Binary Tree
6. Enumeration of Binary Trees
Some other important Binary Tree Traversals :
1. Level order traversal in spiral form
2. Reverse Level Order Traversal
3. BFS vs DFS for Binary Tree
4. Inorder Tree Traversal without Recursion
5. Morris traversal for Preorder
6. Iterative Preorder Traversal
7. Iterative Postorder Traversal Using Two Stacks
8. Diagonal Traversal of Binary Tree
9. Boundary Traversal of binary tree
The expression tree is a binary tree in which each external or leaf node corresponds to the
operand and each internal or parent node corresponds to the operators so for example
expression tree for 7 + ((1+8)*3) would be:
Algorithm Tutorials
Unlike linear data structures (Array, Linked List, Queues, Stacks, etc) which have
only one logical way to traverse them, trees can be traversed in different ways.
A Tree Data Structure can be traversed in following ways:
1. Depth First Search or DFS
1. Inorder Traversal
2. Preorder Traversal
3. Postorder Traversal
We observe that the root node key (27) has all less-valued keys on the left sub-tree and the
higher valued keys on the right sub-tree.
Basic Operations
Following are the basic operations of a tree −
Search − Searches an element in a tree.
Insert − Inserts an element in a tree.
Pre-order Traversal − Traverses a tree in a pre-order manner.
In-order Traversal − Traverses a tree in an in-order manner.
Post-order Traversal − Traverses a tree in a post-order manner.
Defining a Node
Define a node that stores some data, and references to its left and right child nodes.
struct node {
int data;
struct node *leftChild;
struct node *rightChild;
};
Search Operation
Whenever an element is to be searched, start searching from the root node. Then if the data is
less than the key value, search for the element in the left subtree. Otherwise, search for the
element in the right subtree. Follow the same algorithm for each node.
Algorithm
1. START
2. Check whether the tree is empty or not
3. If the tree is empty, search is not possible
4. Otherwise, first search the root of the tree.
5. If the key does not match with the value in the root, search its subtrees.
6. If the value of the key is less than the root value, search the left subtree
7. If the value of the key is greater than the root value, search the right subtree.
8. If the key is not found in the tree, return unsuccessful search.
9. END
The height of the left and right tree for any node does not
differ by more than 1.
The left subtree of that node is also balanced.
The right subtree of that node is also balanced.
A single node is always balanced. It is also referred to as a height-
balanced binary tree.
Example:
Balanced and Unbalanced Binary Tree
AVL tree
The above tree is AVL because the differences between the heights
of left and right subtrees for every node are less than or equal to 1.
Insertion
Deletion
Searching [
An AVL tree may rotate in one of the following four ways to keep
itself balanced:
Left Rotation:
When a node is added into the right subtree of the right subtree, if
the tree gets out of balance, we do a single left rotation.
Left-Rotation in AVL tree
Right Rotation:
If a node is added to the left subtree of the left subtree, the AVL tree
may get out of balance, we do a single right rotation.
Left-Right Rotation:
A left-right rotation is a combination in which first left rotation takes
place after that right rotation executes.
Left-Right Rotation in AVL tree
Right-Left Rotation:
A right-left rotation is a combination in which first right rotation
takes place after that left rotation executes.
1. It is difficult to implement.
2. It has high constant factors for some of the operations.
3. Less used compared to Red-Black trees.
4. Due to its rather strict balance, AVL trees provide
complicated insertion and removal operations as more
rotations are performed.
5. Take more processing for balancing.
Introduction of B-Tree
Read
Discuss
Courses
Practice
Video
The limitations of traditional binary search trees can be frustrating.
Meet the B-Tree, the multi-talented data structure that can handle
massive amounts of data with ease. When it comes to storing and
searching large amounts of data, traditional binary search trees can
become impractical due to their poor performance and high memory
usage. B-Trees, also known as B-Tree or Balanced Tree, are a type of
self-balancing tree that was specifically designed to overcome these
limitations.
Unlike traditional binary search trees, B-Trees are characterized by
the large number of keys that they can store in a single node, which
is why they are also known as “large key” trees. Each node in a B-
Tree can contain multiple keys, which allows the tree to have a
larger branching factor and thus a shallower height. This shallow
height leads to less disk I/O, which results in faster search and
insertion operations. B-Trees are particularly well suited for storage
systems that have slow, bulky data access such as hard drives, flash
memory, and CD-ROMs.
B-Trees maintain balance by ensuring that each node has a
minimum number of keys, so the tree is always balanced. This
balance guarantees that the time complexity for operations such as
insertion, deletion, and searching is always O(log n), regardless of
the initial shape of the tree.
Algorith
Sr. No. m Time Complexity
1. Search O(log n)
2. Insert O(log n)
3. Delete O(log n)
Traversal in B-Tree:
Traversal is also similar to Inorder traversal of Binary Tree. We start
from the leftmost child, recursively print the leftmost child, then
repeat the same process for the remaining children and keys. In the
end, recursively print the rightmost child.
Operations on Heaps
The common operation involved using heaps are:
Binomial Heap
HashSet in Java
Java HashSet class implements the Set interface, backed by a hash
table which is actually a HashMap instance. No guarantee is made
as to the iteration order of the hash sets which means that the class
does not guarantee the constant order of elements over time. This
class permits the null element. The class also offers constant time
performance for the basic operations like add, remove, contains,
and size assuming the hash function disperses the elements
properly among the buckets, which we shall see further in the
article.
Java HashSet Features
A few important features of HashSet are mentioned below:
Implements Set Interface.
The underlying data structure for HashSet is Hashtable.
As it implements the Set Interface, duplicate values are not
allowed.
Objects that you insert in HashSet are not guaranteed to be
inserted in the same order. Objects are inserted based on
their hash code.
NULL elements are allowed in HashSet.
HashSet also
implements Serializable and Cloneable interfaces.
Linear-Search
What is Sorting?
Interpolation Search
Given a sorted array of n uniformly distributed values arr[], write a
function to search for a particular element x in the array.
Linear Search finds the element in O(n) time, Jump Search takes O(√
n) time and Binary Search takes O(log n) time.
The Interpolation Search is an improvement over Binary Search for
instances, where the values in a sorted array are uniformly
distributed. Interpolation constructs new data points within the
range of a discrete set of known data points. Binary Search always
goes to the middle element to check. On the other hand,
interpolation search may go to different locations according to the
value of the key being searched. For example, if the value of the key
is closer to the last element, interpolation search is likely to start
search toward the end side.
To find the position to be searched, it uses the following formula.
o Insert (k): Continue probing until a slot is left open. Put k in the
first empty spot you find.
o Search (k): Continue probing until either an empty slot is found or
the slot's key no longer equals k.
o Delete (k): An intriguing delete procedure. The search can fail if we
just remove a key. Therefore, deleted key slots are specifically
noted as "deleted."
Separate Chaining:
The idea behind separate chaining is to implement the array as a
linked list called a chain. Separate chaining is one of the most
popular and commonly used techniques in order to handle
collisions.
The linked list data structure is used to implement this technique.
So what happens is, when multiple elements are hashed into the
same slot index, then these elements are inserted into a singly-
linked list which is known as a chain.
Here, all those elements that hash into the same slot index are
inserted into a linked list. Now, we can use a key K to search in the
linked list by just linearly traversing. If the intrinsic key for any
entry is equal to K then it means that we have found our entry. If
we have reached the end of the linked list and yet we haven’t
found our entry then it means that the entry does not exist. Hence,
the conclusion is that in separate chaining, if two different
elements have the same hash value then we store both the
elements in the same linked list one after the other.
Example: Let us consider a simple hash function as “key mod 7”
and a sequence of keys as 50, 700, 76, 85, 92, 73, 101
You can refer to the following link in order to understand how to
implement separate chaining with C++.
C++ program for hashing with chaining
Advantages:
Simple to implement.
Hash table never fills up, we can always add more
elements to the chain.
Less sensitive to the hash function or load factors.
It is mostly used when it is unknown how many and how fre
collision resolution
Bubble Sort
For the first position in the sorted list, the whole list is scanned
sequentially. The first position where 14 is stored presently, we search the
whole list and find that 10 is the lowest value.
So we replace 14 with 10. After one iteration 10, which happens to be the
minimum value in the list, appears in the first position of the sorted list.
For the second position, where 33 is residing, we start scanning the rest of
the list in a linear manner.
We find that 14 is the second lowest value in the list and it should appear
at the second place. We swap these values.
After two iterations, two least values are positioned at the beginning in a
sorted manner.
The same process is applied to the rest of the items in the array.
Following is a pictorial depiction of the entire sorting process −
Data Structure and Algorithms Insertion
Sort
This is an in-place comparison-based sorting algorithm. Here, a sub-list is
maintained which is always sorted. For example, the lower part of an
array is maintained to be sorted. An element which is to be 'insert'ed in
this sorted sub-list, has to find its appropriate place and then it has to be
inserted there. Hence the name, insertion sort.
The array is searched sequentially and unsorted items are moved and
inserted into the sorted sub-list (in the same array). This algorithm is not
suitable for large data sets as its average and worst case complexity are
of Ο(n2), where n is the number of items.
It finds that both 14 and 33 are already in ascending order. For now, 14 is
in sorted sub-list.
It swaps 33 with 27. It also checks with all the elements of sorted sub-list.
Here we see that the sorted sub-list has only one element 14, and 27 is
greater than 14. Hence, the sorted sub-list remains sorted after swapping.
So we swap them.
We swap them again. By the end of third iteration, we have a sorted sub-
list of 4 items.
This process goes on until all the unsorted values are covered in a sorted
sub-list. Now we shall see some programming aspects of insertion sort.
We know that merge sort first divides the whole array iteratively into
equal halves unless the atomic values are achieved. We see here that an
array of 8 items is divided into two arrays of size 4.
This does not change the sequence of appearance of items in the original.
Now we divide these two arrays into halves.
We further divide these arrays and we achieve atomic value which can no
more be divided.
Now, we combine them in exactly the same manner as they were broken
down. Please note the color codes given to these lists.
We first compare the element for each list and then combine them into
another list in a sorted manner. We see that 14 and 33 are in sorted
positions. We compare 27 and 10 and in the target list of 2 values we put
10 first, followed by 27. We change the order of 19 and 35 whereas 42
and 44 are placed sequentially.
In the next iteration of the combining phase, we compare lists of two data
values, and merge them into a list of found data values placing all in a
sorted order.
After the final merging, the list should look like this −
Knuth's Formula
h=h*3+1
where −
h is interval with initial value 1
This algorithm is quite efficient for medium-sized data sets as its average
and worst-case complexity of this algorithm depends on the gap sequence
the best known is Ο(n), where n is the number of items. And the worst
case space complexity is O(n).
We compare values in each sub-list and swap them (if necessary) in the
original array. After this step, the new array should look like this −
Then, we take interval of 1 and this gap generates two sub-lists - {14, 27,
35, 42}, {19, 10, 33, 44}
We compare and swap the values, if required, in the original array. After
this step, the array should look like this −
Finally, we sort the rest of the array using interval of value 1. Shell sort
uses insertion sort to sort the array.
Following is the step-by-step depiction −
Tree Sort
Video