ADA Unit 3
ADA Unit 3
for example exploring all the paths to a nearby market to find the
● Arranging the books in a rack using all the possibilities to optimize the
● In fact, daily life activities use a brute force nature, even though optimal
Pros:
problem.
problems.
● The brute force method is ideal for solving small and simpler
problems.
benchmark.
Cons:
design.
paradigms.
Selection Sort
Selection sort is a simple and efficient sorting algorithm that works by repeatedly selecting
the smallest (or largest) element from the unsorted portion of the list and moving it to the
The algorithm repeatedly selects the smallest (or largest) element from the
unsorted portion of the list and swaps it with the first element of the unsorted
part. This process is repeated for the remaining unsorted portion until the entire
list is sorted.
Lets consider the following array as an example: arr[] = {64, 25, 12, 22, 11}
First pass:
● For the first position in the sorted array, the whole array is traversed
value.
● Thus, replace 64 with 11. After one iteration 11, which happens to be
the least value in the array, tends to appear in the first position of the
sorted list.
Selection Sort Algorithm | Swapping 1st element with the minimum in array
Second Pass:
● For the second position, where 25 is present, again traverse the rest of
array and it should appear at the second place in the array, thus swap
these values.
Selection Sort Algorithm | swapping i=1 with the next minimum element
Third Pass:
● Now, for third place, where 25 is present again traverse the rest of the
array and find the third least value present in the array.
● While traversing, 22 came out to be the third least value and it should
appear at the third place in the array, thus swap 22 with element
Selection Sort Algorithm | swapping i=2 with the next minimum element
Fourth pass:
● Similarly, for fourth position traverse the rest of the array and find the
Selection Sort Algorithm | swapping i=3 with the next minimum element
Fifth Pass:
● At last the largest value present in the array automatically get placed
Time Complexity: The time complexity of Selection Sort is O(N2) as there are
● Another loop to compare that element with every other Array element
= O(N)
Auxiliary Space: O(1) as the only extra memory used is for temporary variables
while swapping two values in Array. The selection sort never makes more than
average case.
BUBBLE SORT
swapping the adjacent elements if they are in the wrong order. This algorithm is
not suitable for large data sets as its average and worst-case time complexity is
quite high.
In this algorithm,
● traverse from left and compare adjacent elements and the higher one
● In this way, the largest element is moved to the rightmost end at first.
● This process is then continued to find the second largest and place it
illustration:
First Pass:
The largest element is placed in its correct position, i.e., the end of the array.
Second Pass:
Third Pass:
Bubble Sort Algorithm : Placing the remaining elements at their correct positions
of elements in the input data set. It can limit the efficiency of the
Linear Search is defined as a sequential search algorithm that starts at one end
and goes through each element of a list until the desired element is found,
otherwise the search continues till the end of the data set.
30
Step 1: Start from the first element (index 0) and compare key with each element
(arr[i]).
● Comparing key with first element arr[0]. SInce not equal, the iterator
moves to the next element as a potential match.
● Comparing key with next element arr[1]. SInce not equal, the iterator
moves to the next element as a potentiaL match
Compare key with arr[1]
Step 2: Now when comparing arr[2] with key, the value matches. So the Linear
Search Algorithm will yield a successful message and return the index of the
#include <stdio.h>
// Driver code
int main(void)
{
int arr[] = { 2, 3, 4, 10, 40 };
int x = 10;
int N = sizeof(arr) / sizeof(arr[0]);
// Function call
int result = search(arr, N, x);
(result == -1)
? printf("Element is not present in array")
: printf("Element is present at index %d", result);
return 0;
}
Time Complexity:
● Best Case: In the best case, the key might be present at the first index.
So the best case complexity is O(1)
● Worst Case: In the worst case, the key might be present at the last
index i.e., opposite to the end from which the search has started in the
list. So the worst-case complexity is O(N) where N is the size of the list.
● Average Case: O(N)
Auxiliary Space: O(1) as except for the variable to iterate through the list, no
If you look at the graph below, considering that the salesman starts from the
vertex ‘a’, they need to travel through all the remaining vertices b, c, d, e, f and
get back to ‘a’ while making sure that the cost taken is minimum.
There are various approaches to find the solution to the travelling salesman
problem: naïve approach, greedy approach, dynamic programming approach,
etc. In this tutorial we will be learning about solving travelling salesman
problem using greedy approach.
Travelling Salesperson Algorithm
As the definition for greedy approach states, we need to find the best optimal
solution locally to figure out the global optimal solution. The inputs taken by the
algorithm are the graph G {V, E}, where V is the set of vertices and E is the set of
edges. The shortest path of graph G starting from one vertex returning to the
same vertex is obtained as the output.
Algorithm
Examples
Consider the following graph with six cities and the distances between them −
From the given graph, since the origin is already mentioned, the solution must
always start from that node. Among the edges leading from A, A → B has the
shortest distance.
Then, B → C has the shortest and only edge between, therefore it is included in
the output graph.
There’s only one edge between C → D, therefore it is added to the output graph.
There’s two outward edges from D. Even though, D → B has lower distance
than D → E, B is already visited once and it would form a cycle if added to the
output graph. Therefore, D → E is added into the output graph.
There’s only one edge from e, that is E → F. Therefore, it is added into the output
graph.
Even though, the cost of path could be decreased if it originates from other
nodes but the question is not raised with respect to that.
Example
Minimum Cost: 99
DFS traversal of a Tree
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.
DFS (Depth-first search) is a technique used for traversing trees or graphs. Here
backtracking is used for traversal. In this traversal first, the deepest node is
visited and then backtracks to its parent node if no sibling of that node exists
In the graph, there might be cycles and disconnectivity. Unlike the graph, the
tree does not contain a cycle and are always connected. So DFS of a tree is
relatively easier. We can simply begin from a node, then traverse its adjacent (or
children) without caring about cycles. And if we begin from a single node (root),
and traverse this way, it is guaranteed that we traverse the whole tree as there
is no dis-connectivity,
Examples:
Input Tree:
1. Inorder: 4 2 5 1 3
2. Preorder: 1 2 4 5 3
3. Postorder: 4 5 2 3 1
1. Inorder Traversal :
2. Preorder Traversal :
3. Postorder Traversal:
Uses of Preorder:
Preorder traversal is used to create a copy of the tree. Preorder traversal is also
Uses of Postorder:
Postorder traversal is used to delete the tree. Please see the question for the
deletion of the tree for details. Postorder traversal is also useful to get the
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
};
node->data = data;
node->left = NULL;
node->right = NULL;
return (node);
if (node == NULL)
return;
printPostorder(node->left);
printPostorder(node->right);
if (node == NULL)
return;
/* first recur on left child */
printInorder(node->left);
printInorder(node->right);
if (node == NULL)
return;
printPreorder(node->left);
printPreorder(node->right);
/* Driver code*/
int main()
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
printPreorder(root);
printf("\nInorder traversal of binary tree is \n");
printInorder(root);
printPostorder(root);
getchar();
return 0;
1 2 4 5 3
4 2 5 1 3
4 5 2 3 1
23
45
before moving to any of the nodes of a higher level. This can be done in any of
● the naive one (finding the height of the tree and traversing each level
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
};
// Function prototypes
int h = height(root);
int i;
printCurrentLevel(root, i);
if (root == NULL)
return;
if (level == 1)
if (node == NULL)
return 0;
else {
else
node->data = data;
node->left = NULL;
node->right = NULL;
return (node);
}
int main()
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
printLevelOrder(root);
return 0;
Output
Level Order traversal of binary tree is
1 2 3 4 5
Time Complexity: O(N2), where N is the number of nodes in the skewed tree.
Auxiliary Space: O(1) If the recursion stack is considered the space used is O(N).