Unit Ii
Unit Ii
Linear Search is the simplest search algorithm. It works by checking each element in a list
or array one by one until the desired element is found or the end of the list is reached.
Algorithm:
Time Complexity:
#include <stdio.h>
int main() {
Page 1 of 17
int arr[] = {2, 4, 0, 7, 1, 9, 5};
int target = 7;
int n = sizeof(arr) / sizeof(arr[0]);
2. Binary Search
Binary Search is a much faster search algorithm compared to Linear Search, but it requires
the array to be sorted. It works by repeatedly dividing the search range in half and checking
whether the target element is smaller or greater than the middle element.
Algorithm:
Time Complexity:
Space Complexity: O(1) for the iterative version (constant space), O(log n) for the
recursive version (due to function call stack).
#include <stdio.h>
Page 2 of 17
// Iterative Binary Search function
int binarySearch(int arr[], int low, int high, int target) {
while (low <= high) {
int mid = low + (high - low) / 2;
int main() {
int arr[] = {1, 3, 5, 7, 9, 11, 13};
int target = 7;
int n = sizeof(arr) / sizeof(arr[0]);
Page 3 of 17
printf("Element found at index %d\n", result);
} else {
printf("Element not found\n");
}
return 0;
}
2)Bubble Sort, Selection Sort, Insertion Sort, Quick Sort, Merge Sort.
1. Bubble Sort
Bubble Sort is a simple sorting algorithm that repeatedly steps through the list, compares
adjacent elements, and swaps them if they are in the wrong order. This process is repeated
until the list is sorted.
Algorithm:
Time Complexity:
#include <stdio.h>
Page 4 of 17
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main() {
int arr[] = {64, 25, 12, 22, 11};
int n = sizeof(arr) / sizeof(arr[0]);
bubbleSort(arr, n);
return 0;
}
2. Selection Sort
Page 5 of 17
Selection Sort is an in-place comparison-based sorting algorithm. It repeatedly finds the
minimum element from the unsorted part of the array and swaps it with the first unsorted
element.
Algorithm:
Time Complexity:
3. Insertion Sort
Insertion Sort is a simple sorting algorithm that builds the sorted list one element at a time
by inserting each new element into its correct position in the sorted part of the list.
Algorithm:
Time Complexity:
#include <stdio.h>
Page 6 of 17
int j = i - 1;
int main() {
int arr[] = {64, 25, 12, 22, 11};
int n = sizeof(arr) / sizeof(arr[0]);
insertionSort(arr, n);
Page 7 of 17
printArray(arr, n);
return 0;
}
4. Quick Sort
Algorithm:
Time Complexity:
#include <stdio.h>
Page 8 of 17
for (int j = low; j < high; j++) {
if (arr[j] <= pivot) {
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return i + 1; // return pivot index
}
void quickSort(int arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
int main() {
int arr[] = {64, 25, 12, 22, 11};
int n = sizeof(arr) / sizeof(arr[0]);
Page 9 of 17
printArray(arr, n);
quickSort(arr, 0, n - 1);
return 0;
}
2)Binary trees, Properties, Representation and Traversals (DFT, BFT), Expression Trees
(Infix, prefix, postfix). in ADS&A
A binary tree is a tree data structure in which each node has at most two children, commonly
referred to as the left child and right child.
a. Array Representation:
The binary tree is represented as an array. The root node is stored at index 0.
For any node at index i, the left child is at index 2i + 1, and the right child is at
index 2i + 2.
Page 10 of 17
b. Linked Representation:
Node Structure: A binary tree can be represented using a node structure with three
parts:
o Data: The data contained in the node.
o Left Pointer: A pointer/reference to the left child.
o Right Pointer: A pointer/reference to the right child.
struct Node {
int data;
struct Node* left;
struct Node* right;
};
In Depth-First Traversal, the tree is traversed deeply before backtracking. There are three
types of depth-first traversals:
Inorder (LNR): Traverse the left subtree, visit the root node, then traverse the right
subtree.
o Example: For a tree with the root 1, left child 2, and right child 3, the
traversal will be: 2, 1, 3.
Preorder (NLR): Visit the root node, then traverse the left subtree, then traverse the
right subtree.
o Example: 1, 2, 3.
Postorder (LRN): Traverse the left subtree, then traverse the right subtree, and
finally visit the root node.
o Example: 2, 3, 1.
Page 11 of 17
}
In Breadth-First Traversal, the tree is traversed level by level, starting from the root. A
queue is often used to implement this traversal.
Level Order Traversal involves visiting all nodes at each level of the tree before
moving to the next level.
4. Expression Trees
An expression tree is a binary tree used to represent expressions. Each internal node
represents an operator, and the leaf nodes represent operands (constants or variables).
Expression trees are used for parsing and evaluating expressions.
An infix expression tree has operators at the internal nodes and operands at the leaves. The
order of operations is preserved in the tree.
Example: Expression: (A + B) * C
Infix tree:
*
/ \
+ C
/\
A B
In the prefix expression tree, the operator appears before its operands.
Page 12 of 17
Prefix tree:
*
/ \
+ C
/\
A B
In the postfix expression tree, the operator appears after its operands.
Postfix tree:
*
/ \
+ C
/\
A B
Infix to Prefix/Postfix:
o Infix to Prefix: Reverse the infix expression, convert it to postfix, and then
reverse the result.
o Infix to Postfix: Use the Shunting Yard algorithm or a stack-based approach
to convert infix to postfix.
Space Complexity:
Space for Representation: O(n), where n is the number of nodes (due to pointers in
the linked representation).
Traversal Space: O(h) for DFS (stack space) and O(n) for BFS (queue space).
A graph is a non-linear data structure consisting of a set of vertices (or nodes) connected by
edges (or arcs). Graphs are used to represent various real-world problems such as networks,
social media connections, paths in a maze, and more.
Page 14 of 17
a. Adjacency Matrix:
A 2D array adj[][] where adj[i][j] is 1 (or the weight of the edge) if there is
an edge from vertex i to vertex j, and 0 (or infinity for weighted graphs) if there is
no edge.
Pros:
o Simple to implement.
o Efficient for dense graphs (graphs with many edges).
Cons:
o Wastes space for sparse graphs (graphs with few edges).
o O(1) time complexity for checking if there is an edge between two vertices,
but O(n²) space complexity.
lua
Copy
0 1 2 3
---------------
0|0 1 0 1
1|0 0 1 0
2|1 0 0 0
3|0 0 0 0
b. Adjacency List:
An array of lists (or vectors). Each list corresponds to a vertex and contains a list of its
adjacent vertices (i.e., the vertices to which it is directly connected by edges).
Pros:
o More space-efficient for sparse graphs.
o O(1) time complexity for adding an edge, and the space complexity is O(E),
where E is the number of edges.
Cons:
o Checking if an edge exists between two vertices takes O(n) time.
0: 1 -> 3
1: 2
2: 0
3: (no adjacent vertices)
Page 15 of 17
In this list:
3. Graph Traversals
Graph traversal refers to the process of visiting all vertices in a graph. There are two primary
types of graph traversal:
DFS explores as far as possible along each branch before backtracking. It's implemented
using recursion or a stack.
Steps:
1. Start at a vertex, mark it as visited.
2. Visit all its unvisited adjacent vertices recursively.
3. Backtrack when no more unvisited adjacent vertices are found.
Applications:
BFS explores all the neighbors of a vertex before moving to the next level. It uses a queue to
keep track of vertices to be explored.
Steps:
1. Start at a vertex, mark it as visited, and enqueue it.
2. Dequeue a vertex, visit all its unvisited adjacent vertices, and enqueue them.
3. Repeat the process until the queue is empty.
Applications:
Page 16 of 17
4. Graph Applications
Shortest Path: Algorithms like Dijkstra's or Bellman-Ford for finding the shortest
path in weighted graphs.
Topological Sort: Used in directed acyclic graphs (DAGs) for ordering vertices in a
way that for every directed edge u → v, vertex u comes before vertex v.
Cycle Detection: DFS and BFS are commonly used for detecting cycles in directed
and undirected graphs.
Minimum Spanning Tree: Algorithms like Prim's and Kruskal's for finding the
minimum spanning tree in a weighted graph.
DFS Time Complexity: O(V + E) and Space Complexity: O(V) due to recursion
stack or visited array.
BFS Time Complexity: O(V + E) and Space Complexity: O(V) due to the queue
used to store vertices.
Page 17 of 17