Chapter 4 Algorthms 1 31
Chapter 4 Algorthms 1 31
Chapter 4 Algorthms 1 31
ALGORITHMS
Syllabus: Algorithms: Analysis, Asymptotic notation, Notions of space and time complexity, Worst- and average-case
analysis; Design: Greedy approach, Dynamic programming, Divide-and-conquer; Tree and graph traversals, Connected
components, Spanning trees, Shortest paths; Hashing, Sorting, Searching. Asymptotic analysis (best, worst, average
cases) of time and space, Upper and lower bounds, Basic concepts of complexity classes — P, NP, NP-hard, NP-complete.
Problem 4.1: Consider the following functions: Problem 4.2: Consider the following functions:
f (n) = n f (n) = n
n g(n) = n
g(n) =
8
For f(n) = O(g(n)), find the values of c and n0.
For f(n) = Q(g(n)), find the values of c1, c2 and n0.
Solution: From the definition of Big-O notation, we
Solution: From the definition of theta (Q) notation, have
f (n) ≤ c(g(n)) ∀n ≥ n0
we have
n0 c ⋅ n ≤ n2 ∀ n ≥ n0
Figure 4.2 | Big-O notation (O). The above condition is satisfied. So, c = 1 and n0 = 1.
O(nn)
O(an)
O(nk)
O(n2)
O(n)
Time
O(√n)
Olog(n)
O(log(log n)
O(1)
Complexities
Figure 4.4 | Time complexities in increasing order.
A hash table is a data structure used for hashing. It is 4.3.3.2 Open Addressing
an associative array that contains keys with values. In
an array, indices are required to be integer, but a hash 1. Collision occurs if the hash function produces the
table allows floating point numbers, strings, array or same position occupied by another item. In this
structures as keys. Hash tables provide efficient lookup case, another open position is searched.
operation, that is, whenever a key is given, hash table
Example: Hash code produced for `White’ is 22.
provides associated value in almost constant time com-
But position 22 is already occupied, so it is placed
plexity. This transformation is done using hash function.
at position 23.
2. There are three ways of finding an open position.
4.3.2 Hashing Functions
This process is known as probing. To search any
A hashing function is a transformation function, coded item in hash table, probing may be required.
to return a value based on key. If h is a hash function Example: When item “white” is searched, first we
that takes key k as parameter, will compute the index at look for it at position 22. If it is not found there, we
which value is placed. If h is a hash function that takes move to next location. The search will be stopped
key as a parameter, it will compute index where value only when an empty position is encountered.
22 When 0 Arrow
23 White 1 Ape
24 Yellow 2 Cat
25 Zero 3
4 Eye
4.3.3.3 Linear Probing 5 Ball
In case of linear probing the probe sequence is h(key), ... ... ...
h(key) + 1, h(key) + 2, …, uptill required. 22 When
Examples: The item `Ape’ (h = 0) will be placed at
23 White
position 1, because position 0 is already occupied. then
`Ball’ (h = 1): try to place it at position 1, 1+1, 1+2. 24 Yellow
Position 3 is open so it will be placed here.
25 Zero
Advantage: If open position is available, linear probing
will definitely find it.
Disadvantage: It may fail to find an existing open
Disadvantage: If there are clusters of filled positions,
position. For example, let table size = 10, and x denote
then length of subsequent probes increases. Probe length
the occupied blocks. Trying to insert a key with h(key) =
is the number of positions considered during a probe.
0 offsets the probe sequence shown in italic.
0 Arrow
0 x 5 x 25
1 Ape
2 Cat 1 x 1 81 6 x 16 36
3 Ball 2 7
4 Eye 3 8
5 x
4 x 4 64 9 9 49
... ... ...
Examples:
0 Arrow
1. h1 = our previous h
2. h2 = number of characters in the string 1 1
3. `Ape’ (h1 = 0, h2 = 3): try 0, 0 + 3 − open!
`Ball’ (h1 = 1, h2 = 4): try 1 − open!
2 Cat
4.
3 Ball
Advantages:
4 Eye
1. It combines the good features of linear and qua-
dratic probing: 5
2. It reduces clustering
3. It will find an open position if there is one, pro- ... ... ...
vided the table size is a prime number 22 When
23 White
0 Arrow 24 Yellow
1 Ball 25 Zero
2 Cat
3 Ape
4.4 BINARY HEAP
4 Eye
5 A binary heap is a binary tree with two additional constraints:
... ... ... 1. Binary heap should satisfy the property of com-
22 When plete binary tree.
2. It should satisfy the heap ordering property, that
23 White is, all the nodes should be either greater than or
equal to or less than or equal to its children.
24 Yellow
According to the heap ordering property, binary heaps
25 Zero
are of two types:
Example 4.6
1. Insert the given value (5) in the given min-heap tree. 4. To satisfy the property of min-heap, swap (5, 7).
2. Element 5 is inserted at position of left child of node 5. Now, element 5 is in its right position. This is the
14. To satisfy the property of min-heap, swap (5, 14). final tree.
3. To satisfy the property of min-heap, swap (5, 10).
7 7
7
10 17 10 17
10 17
14 23 21 42 5 23 21 42
14 23 21 42
5 14
1 2 3
7 5
5 17 7 17
10 23 21 42 10 23 21 42
14 14
4 5
4. This represents the final tree, which is in the min- a set of numbers in an ascending or descending
heap property. order.
3. In internal sorting, the data which is to be sorted fits
7 42 into the main memory. Internal sorting has an advan-
tage of the random access nature of the main memory.
10 17 10 17 4. In external sorting, large amount of data is
sorted. This large amount of data cannot be fit
14 23 21 42 14 23 21 in main memory, so the data is placed in auxil-
iary memory. When sorting has to perform, small
1 2
chunks of data are brought into main memory,
10 10 sorted and placed back to a temporary file. At last
all the sub-files are merged in one large file.
42 17 14 17 5. In stable sorting, the order of equal elements is
preserved in a sorted list. Some of the sorting algo-
rithms that show characteristics of stable sort are
14 23 21 42 23 21
insertion sort, bubble sort, merge sort, etc.; whereas
3 4 heap sort, quick sort, etc., are not stable sorts.
6. In-place sorting: In this, the input is transformed
using a data structure with a small, constant amount
4.4.3 Time Complexity of extra storage space. The input is usually overwrit-
ten by the output as the algorithm executes. Quicksort
1. The worst-case running time for insertion is is commonly described as an in-place algorithm.
O(log n) because at most (log n) swaps are required 7. Measurement of time complexity: The time
to stable the min-heap property of the tree. complexity of a sorting algorithm is measured
2. The worst-case running time for deletion is O(log n) by the number of critical operations performed.
because at most (log n) swaps are required to stable Examples of critical operations are as follows:
• Key comparisons
the min-heap property of the tree.
Some important points of binary heap are as follows: • Movements of records
1. Because of its structure, a heap with height k will • Interchanges of two records
have between 2k and 2k+1 - 1 elements. Therefore, 8. We use asymptotic analysis to denote the time
a heap with n elements will have height = log2n. efficiency of an algorithm. Efficiency of an algorithm
2. In heap data structure, element with highest or lowest also depends on the type of data for input, so we
priority is stored as root element. Heap is not consid- define best-, worst- and average-case efficiencies.
ered as sorted structure, rather it is partially ordered.
There is no relation among nodes at a given level. 4.5.1 Linear Search
Heap is very useful data structure for implement
ing priority queues. Element with highest priority Linear search is a sequential way of finding an element in
can be easily removed. a given list. Linear search is a special case of brute force
3. Since a binary heap is a complete binary tree, it search. Its worst case is proportional to the number of
can be easily represented as an array, and an array- elements in list.
based representation is space efficient. If the parent
node is stored at index I, the left child can be cal-
4.5.1.1 Pseudocode for Linear Search
culated by 2 ×I + 1 and right child by 2 ×I + 2.
LINEAR_SEARCH (A[ ], x)
4.5 SEARCHING AND SORTING 1. i = 1
2. while (A[i] = = x and i < n)
3. i = i + 1
4. if (A[i] = = x)
Searching and sorting are the most common activities
5. return i
performed by the computer. These operations are the 6. else return 0
most important part for managing the data.
1. Searching is the algorithmic process of finding an 4.5.1.2 Time Complexity
item in a collection of items. The search result is
either true or false depending on whether or not From the analysis of above pseudocode, it can be
the item is present or not in the list. observed that with the growth of input list, average and
2. Sorting is ordering a list of objects according to a worst case complexities also grow linearly. In general, if
given condition or property. For example, ordering there are n elements in the list, the worst-case requires n
The insertion sort inserts each element into its proper The worst-case running time is O(n2)
position. It chooses one element, inserts it to its posi- The best-case running time is O(n)
tion and shifts the rest of the list by one location. This
process is repeated until no input element remains. Step- 4.5.6 Heap Sort
by-step procedure is given as follows.
1. Take an element from unsorted list. Heap sort is one of the comparison based sort that uses
2. Compare that element with sorted list from right heap data structure. It is a special case of selection sort.
to left. Its typical implementation is not stable, but can be made
3. Shift the list. stable. Heap can be built by the following two types:
Here, it is assumed that first element is already sorted. 1. Min-Heap: The parent node will be less than or
equal to its children nodes. So, the minimum ele-
ment will be at root.
4.5.5.1 Pseudocode for Insertion Sort 2. Max-Heap: The parent node will be greater than
or equal to its children nodes. The maximum ele-
INSERTION_SORT(A)
1. for j = 2 to n ment will be at the root.
2. key A [j]
3. // Insert A[j] into the sorted sequence A[1..j-1] 4.5.6.1 Heap Sort Algorithm for Sorting in
4. j i– 1 Increasing Order
5. while i > 0 and A[i] > key
6. A[i+1] A[i] 1. First build a max-heap from the input List.
7. i i– 1 2. In max heap, the largest element is at the root. So,
8. A[j+1] key swap the root with last element. Re-heapify the
tree. Repeat the above steps until the size of the 4.5.6.3 Pseudocode for BuildHeap Function
heap is greater than 1.
•• Heapify function: Heapify is an important BUILD_HEAP(A)
subroutine for manipulating max-heaps. Its 1. heapsize <- length(A)
2. for i <- floor( length/2 ) down to 1
inputs are an array A and an index i into the
3. Heapify(A, i)
array. When Heapify is called, it is assumed
that the binary tree rooted at left(i) and right(i) 4.5.6.4 Pseudocode for Heap Sort
is max_heap, but that A[i] may be smaller
than its children, thus violating the max-heap HEAP_SORT(A)
property. 1. BuildHeap(A)
•• Build Heap function: Heapify procedure 2. for i <- length(A) down to 2
is used in a bottom-up to convert an array A 3. exchange A[1] <-> A[i]
4. heapsize <- heapsize -1
into a max-heap. The elements in the subarray
5. Heapify(A, 1)
A[(n/2 + 1)⋅⋅⋅n] are all leaves of the tree, and
so each is a one-element heap to begin with. The
procedure BuildHeap goes through the remain- 4.5.6.5 Recurrence Relation of Heapify
ing nodes of the tree and runs Heapify on each Function
node. The recurrence relation of Heapify() is
2n
4.5.6.2 Pseudocode for Heapify Function T (n) ≤ T + Q(1)
3
HEAPIFY(A, i)
1. le <- left(i) 4.5.6.6 Time Complexity
2. ri <- right(i)
3. if (le<=heapsize) and (A[le]>A[i]) The time complexity of Heapify() is O(log n). The time
4. largest <- le
5. else
complexity of BuildHeap() is O(n log n), and the overall
6. largest <- i time complexity of the heap sort is O(n log n).
7. if (ri<=heapsize) and (A[ri]>A[largest])
8. largest <- ri 4.5.6.7 Applications of Heap Sort
9. if (largest != i)
10. exchange A[i] <-> A[largest] 1. It sorts a nearly sorted (or k-sorted) array.
11. HEAPIFY(A, largest) 2. It sorts k largest (or smallest) elements in an array.
Example 4.11
Let {6, 5, 3, 1, 8, 7, 2, 4} be the list that we want to sort recursively checked if another swap is needed, to keep
from the smallest to the largest. (Note: For `building larger numbers above smaller numbers on the heap
the heap’ step, larger nodes do not stay below smaller binary tree.)
node parents. They are swapped with parents, and then 1. Build the heap:
Example 4.12
Sort the given list of elements: (54, 26, 93, 17, 77, 31, 44, Step 2: After dividing the array, merge sort calls the
55 and 20). MERGE function to put the subarray into a sorted order.
Step 1: A recursive merge sort is called on the array Array A:
of elements. Merge sort is a recursive function which
divides an array into two parts; and calls itself recur- 54 26 93 17 77 31 44 55 20
sively to divide the array into sub-parts until each part
is having one element.
p r
Merge sort (A, 0, 8) 54 26 93 17 77 31 44 55 20
0 1 2 3 4 5 6 7 8
54 26 93 17 77 31 44 55 20
54 26 93 17 77 31 44 55 20
54 26 93 17 77 31 44 55 20
54 26
Merge (A, p, q, r)
54 26 93 17 77 31 44 55 20
26 54 93 17 77 31 44 20 55
26 54 93 17 77 31 44 20 55
17 26 54 77 93 20 31 44 55
Completed 17 20 26 31 44 54 55 77 93
3. Output each object from the input sequence fol- • It does not have any parallel edge.
lowed by decreasing its count by 1.
(a) Process the input data: 1, 4, 1, 2, 7, 5, 2. Posi-
tion of 1 is 2.
(b) Put data 1 at index 2 in the output. Decrease
count by 1 to place the next data 1 at an index 1
smaller than this index.
(c) Put data 2 at index 4 in the output. Decrease Figure 4.5 | Simple graph.
count by 1 to place the next data 2 at an index 3
smaller than this index. 2. Multigraph: A graph with a self-loop and parallel
(d) Now, move to the next element 3 which has count 4, edges is called a multigraph (Fig. 4.6).
and index 4 is already filled by 2 which means ele-
ment 3 does not exist in the given input list.
(e) Follow this process for all the elements.
4.6.2.2 Regular Graph graph. If adj[i][j] = 1, this indicates there exists an edge
between vertices i and j; otherwise, the value will be 0.
A graph is called a regular graph if all of its vertices have The adjacency matrix for undirected graph is symmet-
the same degree (Fig. 4.8). ric. Weights can also be represented by this matrix. The
value adj[i][j] = w means weight of edge from i to j is w.
Vertex 1 2 3 4 5
1 2
1 0 1 1 1 0
5 2 1 0 1 1 1
3 1 1 0 1 0
1-Regular 2-Regular 3-Regular 4 1 1 1 0 1
Figure 4.8 | Regular graph.
3 4
5 0 1 0 1 0
The important terms are given as follows: knapsack exactly; otherwise, we could add a fraction of
1. Solution space: The set of all possible solutions one of the remaining objects and increase the value of
for given n inputs is called solution space. the load. Thus, in an optimal solution, nSi = 1xiwi = W.
2. Feasible solution: The feasible solution is one of
the solutions from the solution space which satis- 4.7.2.1 Pseudocode for Fractional
fies the given condition.
Knapsack
3. Optimal solution: The optimal solution is one
of the feasible solutions which optimizes our goal. Greedy-fractional-knapsack (w, v, W)
1. for i =1 to n
4.7.1 Applications of Greedy Approach
2. Do x[i] =0
The following are the applications of the greedy approach: 3. weight = 0
4. while weight < W
1. Knapsack problem (fractional)
5. Do i = best remaining item
2. Job sequence with deadline
6. if ( weight + w[i] ≤ W)
3. Huffman coding
4. Minimum cost spanning tree: 7. Then x[i] = 1
a. Kruskal’s algorithm 8. weight = weight + w[i]
b. Prim’s algorithm 9. else
5. Singlesource shortest path:
10. x[i] = (w - weight) / w[i]
a. Dijkstra’s algorithm
b. Bellman—Ford algorithm 11. weight = W
12. Return x
4.7.2 Fractional Knapsack
4.7.2.2 Time Complexity
In this problem, items are given along with its weight
and profit. The target is to maximize the profit consider- If the ratio of vi/wi is already sorted in decreasing order,
ing the weight constraint. Unlike 0-1 knapsack problem, then the time taken by the while loop will be O(n). So,
fraction of item can be considered. Fractional knapsack the total time required will be O(n log n). If heap data
problem can be solved by Greedy approach. structure is used, which keeps highest value/weight ratio
Greedy Algorithm: The solution can be obtained by at root. The construction of heap will take O(n) time
making different choices. At each stage, the best possible and while loop will take O(log n) time (heap property is
choice is made. In fractional knapsack, first of all profit restored for each root removal). This does not improve
value/weight ratios are calculated and then sorted in the worst case, but it is faster if small number of items
descending order. Item with highest value/weight ratio are to be filled in knapsack.
is chosen and added in the collection. The maximum
weight is checked after adding each item. If the entire Example 4.16
item cannot be included, then fraction of it is added to
Consider the following details:
the collection.
1. Knapsack size = 20
2. Number of objects = 3
Example 4.15
There are n items in a store. For i = 1, 2, …, n, item i Object Obj1 Obj2 Obj3
has weight wi > 0 and worth vi > 0. A thief can carry a Profit 25 24 15
maximum weight of W pounds in a knapsack. In this ver- Weight 18 15 10
sion of a problem, the items can be broken into smaller
pieces, so the thief may decide to carry only a fraction xi Solution:
of object i, where 0 ≤ xi ≤ 1. Item i contributes xiwi to
the total weight in the knapsack, and xivi to the value Step 1: Calculate ratio (profit/weight):
of the load. Object Obj1 Obj2 Obj3
In symbol, the fraction knapsack problem can be Profit 25 24 15
stated as follows.
Weight 18 15 10
Maximize nSi = 1xivi subject to constraint nSi = 1xiwi
≤ W. It is clear that an optimal solution must fill the
Ratio 1.38 1.6 1.5
Step 2: Put according to decreasing ratio (profit/ 4.7.3.2 Pseudocode for Huffman Coding
weight):
HUFFMAN(f[1...n])
Object Obj2 Obj3 Obj1 1. T = empty binary tree
2. Q = priority queue of pairs (i, f[i]),
Profit 24 15 25
i = 1...n, with f as comparison key
Weight 15 10 18 3. for each k = 1...n − 1
Ratio 1.6 1.5 1.38 4. i = extractMin(Q)
5. j = extractMin(Q)
Step 3: Put items into the knapsack till the knapsack 6. f[n + k] = f[i] + f[j]
is full: 7. insertNode(T, n + k) with children i, j
8. insertRear(Q,(n + k, f[n + k]))
(a) Put object 2 into the knapsack; it will add (value = 9. return T
24 and weight = 15) to the knapsack. Knapsack has
5 units capacity remaining.
(b) Now object 3 cannot be put completely into the 4.7.3.3 Time Complexity
knapsack, so put a fraction of it. Add (value = 7.5
and weight = 5) to the knapsack. Knapsack is com- From the above pseudocode, we can see that with each
pletely full, which means no other object can be put iteration,the problem size is reduced by 1. Hence, there
into it. are exactly n iterations. The ith iteration consists of
locating the two minimum values in a list of length n −
Step 4: Total knapsack value = 31.5 (which is optimum).
i + 1. This is a linear operation, and so Huffman’s
algorithm clearly has a time complexityof O(n2).
4.7.3 Huffman Coding However, it would be faster to sort the weights ini-
tially, and then maintain two lists. The first list consists of
Huffman coding is a common technique of encoding, weights that have not been combined yet, and the second
includinglossless data compression. The algorithm’s list consists of trees that have been formed by combining
output can be viewed as a variable-length code table weights. This initial ordering is obtained at the cost of
for encoding a source symbol (such as a character in a O(n log n). Obtaining the minimum two trees at each step
file). Huffman coding is based on the frequency of occur- then consists of two comparisons (comparing the heads of
rence of a data item (pixel in images). The main aim the two lists, and then comparing the larger item with the
of Huffman coding is to encode the data that occurs item after the smaller). The ordering of the second list can
frequently using less number of bits. Code books store be maintained cheaply by using a binary search to insert
codes that are constructed for images. Both the code new elements. Since at step i there are i − 1 elements in
book and encoded data are transmitted to decode the the second list, O(log i) comparisons are needed for inser-
information. tion. Over the entire duration of the algorithm, the cost of
Huffman codes can be constructed using following two keeping this list sorted is O(n log n). Therefore, the overall
ideas: time complexity of Huffman’s algorithm is O(n log n).
1. For an optimum code, symbols that have high
probability should be assigned shorter code words. Example 4.17
2. To make optimum prefix code, two symbols that
In the following example five different symbols are given
occur least frequently should be assigned same
along with their frequency.
length.
Symbol Frequency
4.7.3.1 Principle of Huffman Codes
A 24
1. Starting with the two least probable symbols, g B 12
and d, of an alphabet A, if the code word for g is C 10
[m]0, the code word for d would be [m]1, where [m] D 8
is a string of 1s and 0s.
2. Now, the two symbols can be combined into a E 8
group, which represents a new symbol y in the
There are a total of 186 bits (with 3 bits per code word).
alphabet set.
3. The symbol y has the probability P(g ) + P(d ). Here, the least frequency symbols are E and D. First
Recursively, determine the bit pattern [m] using of all, we will connect them and frequency of node will
the new alphabet set. become 16. Then B and C are combined to make the
frequency 22. These will be two new nodes. In the next 3. At each step, an edge is added to the graph that
step, these two nodes are brought together and act as has minimum weight and is the neighbour to the
subordinate to the root node. A also acts as subordinate previous vertices.
to root node.
Steps of Prim’s Algorithm
1. Find the minimum weight edge from graph and
4.7.3.4 Code Tree According to Huffman
mark it.
2. Consider the neighboring edges of the selected
edges and mark the minimum weight edge among
those edges.
0 62 1 3. Continue this until we cover n-1 edges.
4. The resultant tree is minimum spanning tree and it
A
should always be connected.
24 0 38 1 Input: Undirected connected weighted graph G = (V, E )
in adjacency list representation, source vertex s in V and
w is an array representing weights of edges.
Output: p[1⋅⋅⋅|V |], representing the set of edges com-
0 22 1 16 1
0
posing an MST of G.
B C E
Note: The field p(v) names the parent of v in the tree.
D
12 10 8 8
Key(v) is the minimum weight of any edge connect-
ing v to a vertex in tree. Key(u)←∞ means there is no
Symbol Frequency Code Code Total such edge.
Length Length
PRIM (G, w, s)
A 24 0 1 24 1. for each u in V(G)
B 12 100 3 36 2. do key(u) ∞
3. π(v) NIL
C 10 101 3 30
4. key [r] 0
D 8 110 3 24 5. Q V [G]
E 8 111 3 24 6. while Q != empty
7. do u Extract-Min(Q)
8. for each v in Adjacent[u]
9. do if v ∈ Q and w(u, v) < key [u]
The total length is 138 bits.
Prim’s algorithm is a method to find minimum spanning Problem 4.5: Use Prim’s algorithm to find an MST in
tree. In this algorithm minimum spanning tree formed the following weighted graph. Use alphabetical order
should always be connected. Prim’s algorithm is an to break ties.
example of Greedy approach. b 5 d
Properties of Prim’s Algorithm 2 2
Step 3: Now select the next minimum weight edge and 2. Calculate the temporary distance of neighbours of
draw the corresponding edge in disconnected graph. active nodes. Distance is calculated by adding up
the weights associated with those edges.
b c d 3. Update the distance, and set the current node an
2 antecessor if such a calculated distance of a node is
smaller as the current one. This step is also called
i update and is Dijkstra’s central idea.
a e
4. Set the node as active node which has minimal tem-
porary distance. Mark the distance as permanent.
5. Repeat steps 2 to 4 until there are no nodes left
h g f with a permanent distance, whose neighbours still
1 2 have temporary distances.
Here, there are two edges containing weight 2, add all
possible edges of same weight until they form loop in the Dijkstra’s Pseudocode
tree (since tree doesnot contain any loop but a graph
DIJKSTRA (G , S):
may contain). That is why edge(g,f) and edge(i,c) both 1. for each vertex v in Graph:
are added. 2. distance[v] := infinity
Step 4: Continue this process and check for the next 3. previous[v] := undefined
smallest edge and add it into tree. Do this till we get 4. distance[ S ] := 0
(n − 1) edges in the tree. 5. Q := the set of all nodes in Graph
6. While Q is not empty:
The final minimum spanning tree would be: 7. u := node in Q with smallest distance[ ]
8. remove u from Q
b c d 9. for each neighbour v of u:
10. alt := distance[u] + distance_between(u, v)
11. If alt < distance[v]
i e 12. distance[v] := alt
a
13. previous[v] := u
14. Return previous[ ]
h g f
Time Complexity
Like Prim’s algorithm, Dijkstra’s algorithm runs in O(E
4.7.5 Single-Source Shortest Path log V) time.
1. Dijkstra’s algorithm with list: O(V2)
Given a weighted graph G, find the shortest path from 2. Dijkstra’s algorithm with modified binary heap:
a given vertex to every other vertex in G. Note that we O((E + V) log V )
can solve this problem quite easily with BFS traversal in 3. Dijkstra’s algorithm with Fibonacci heap: O(E +
the special case when all weights are equal. The Greedy V log V )
approach to this problem is repeatedly selecting the best
choice from those available at that time. Example
The following are the steps:
1. Start from the source node; find the distance of all
4.7.5.1 Dijkstra’s Algorithm
nodes reachable from the source.
Dijkstra’s algorithm is a single source shortest path algo- 2. Then pick the node which has the minimum dis-
rithm. It calculates the shortest distance starting from tance, from the pool of nodes. Source
the start node till another node in the graph. While cal- 3. Calculate again the distance from the selected A B C
culating the shortest distance, it excludes the longer dis- node, and follow the above two steps till the entire ∞ ∞ ∞ ∞
tance paths. Dijkstra’s algorithm does not operate on nodes are selected. Nil Nil N
negative weights. For calculating shortest distance with O 10 3 ∞
2 A Nil A A N
negative edges, Bellman-Ford algorithm is used. Steps to B D
10 O 4
perform Dijkstra’s algorithm are as follows:
1 4 8 7 9 AC Nil C
1. Assign all the nodes with distance infinity and 0 to A
3 O
initial node.Distance of start node s permanent and Nil
3 ACB
of all the other nodes is temporary.Set start node
C E O
as active node.
ACBD Nil
Source to know that the node has been explored before or not.
A B C D E The re-traversal becomes more for dense graph, which
∞ ∞ ∞ ∞ ∞ Cost increase computation time. Tree traversal is a special
Nil Nil Nil Nil Parent case of graph traversal. The following are two graph
O 10 3 ∞ ∞ traversal methods:
2 A Nil A A Nil Nil
B D 1. Breadth-first traversal (BFT)
Source O 4 11 6 2. Depth-first traversal (DFT)
A 4 B8 C 7 D 9 E AC Nil C C C
2
∞ ∞ ∞ ∞ ∞ Cost O 6 6 B D
4.8.1 Breadth-First Traversal
Nil Nil Nil Nil ParentNil
ACB B C A 1
CO 10 3 ∞E ∞
3
O 6 3 C The breath-first
E traversal starts from the root node and
Nil A A Nil Nil ACBD Nil 3 traverses all its neighbours. Then for each neigh-
C then
O 4 11 6 bour, its corresponding unvisited neighbour is processed.
Nil C C C
2 The pseudocode for BFT is given as follows:
O 6 6 B D
Nil B C A 1 BST (V)
1. visited(V) =1
O 6 3 C
3
E 2. add(V, Q)
Nil C 3. while(Q is not empty)
4. u = delete(Q)
4.7.5.2 Bellman—Ford Algorithm 5. for all x adjacent to u
6. if( x is not visited)
The Bellman—Ford algorithm is used to compute 7. visited(x) = 1
single source shortest path to all other vertices of 8. add(Q, x)
weighted directed graph. This algorithm also consid-
ers negative weights of graph edges. This algorithm 4.8.1.1 Time Complexity
is slower but is capable of even finding a negative
weight cycle in graph. The time complexity of BFT is O(V + E), where V is
the number of vertices in the graph and E is the number
Bellman-Ford Pseudocode of edges in the graph.
J
Graph traversal means visiting all the nodes in a graph in
some order. In graph traversal, some nodes may be vis- Solution: A is the starting node and Q is a queue data
ited more than once. This is because it is not necessary structure to store the values.
3. u = delete (Q) → B
12. The queue is empty, which means graph is tra-
For all adjacent nodes to B which are not already
versed completely.
added in the queue, Add (Q, X), where X = (D, E)
is the adjacent node to B.
C D E
4.8.2 Depth-First Traversal
4. u = delete (Q) → C
As already discussed, there are many ways of tree tra-
For all adjacent nodes to C which are not already
versal. Consider the tree given in Fig. 4.10:
added in the queue, Add (Q, X), where X = (F, G)
is the adjacent node to C.
Tree
D E F G
5. u = delete (Q) → D I Root
For all adjacent nodes to D which are not already
added in the queue, Add (Q, X), where X = (H) is
the adjacent node to D. F K
E F G H
6. u = delete (Q) → E A H Z
For all adjacent nodes to E which are not already
added in the queue, Add (Q, X), where X = (F) is
the adjacent node to E. D
F G H Figure 4.10 | DFT of a tree.
7. u = delete (Q) → F
For all adjacent nodes to F which are not already Preorder traversal for given tree: I F A D H K Z
added in the queue, Add (Q, X), where X = (I) is Preorder traversal also results in depth first traversal.
the adjacent node to F. This is because the traversal goes deeper before travers-
G H I ing its siblings. In this tree, the descendants of F, that
is, A, H, D are traversed first and after that sibling of F,
8. u = delete (Q) → G that is, K are traversed.
For all adjacent nodes to G which are not already
added in the queue, Add (Q, X), where X = (I) is
the adjacent node to G. 4.8.2.1 Pseudocode for DST
H I DFT (V)
1. visited (V) =1
9. u = delete (Q) → H 2. for all x adjacent to V
For all adjacent nodes to H which are not already 3. if (x is not visited)
added in the queue, Add (Q, X), where X = (J) is 4. visited (x) =1
the adjacent node to H. 5. DFT (x)
I J
The above is the recursive code for DFT.
H E C
8. POP (S) → E
Solution: A is the starting node and S is a stack data For all adjacent nodes to E which are not already
structure to store the values. Stack is internally used added in the stack, PUSH (S, X). Every neighbour
by the recursive call. element will be stored in the stack from right to left.
Here, X = (F) is the adjacent node to E.
DFT (A)
1. Visited (A) =1 C
PUSH(S, A) 9. POP (S) C
A For all adjacent nodes to C which are not already
added in the stack, PUSH (S, X). Every neighbour
2. POP(S) → A element will be stored in the stack from right to left.
For all adjacent nodes to A which are not already Here, X = (F) is the adjacent node to C.
added in the stack, PUSH (S, X). Every neighbour
element will be stored in the stack from right to left.
Here, X = (B, C) is the adjacent node to A. 10. The stack is empty, which means the graph is
traversed completely.
B C
3. POP(S) → B
For all adjacent nodes to B which are not already 4.9 DYNAMIC PROGRAMMING
added in the stack, PUSH (S, X). Every neighbour
element will be stored in the stack from right to left.
Here, X = (D, E) is the adjacent node to B. Dynamic programming is a method for solving complex
problems by breaking them down into simpler sub-prob-
D E C lems. It is applicable to problems exhibiting the proper-
ties of overlapping sub-problemsand optimal substructure.
Dynamic programming algorithms are used for optimiza- The total running time = O(2n).
tion (e.g. finding the shortest path between two points, or Note: Most of the recursive programs contain very less
the fastest way to multiply many matrices). A dynamic number of distinct calls and more number of repeated sub-
programming algorithm will examine all possible ways to problems or function calls. These problems are known as
solve the problem and will pick the best solution. overlapping sub-problems.
Time Complexity
Fib(5) Fib(4)
1. Fibonacci series without dynamic programing
[space = O(n) and time = O(2n)]
Fib(4) Fib(3) Fib(3) Fib(2) 2. Fibonacci series with dynamic programing [space =
Level 6 O(n) and time = O(n)]
Fib(3) Fib(2) Fib(2) Fib(1) Fib(2) Fib(1)Fib(1) Fib(0) 4.9.3 0/1 Knapsack
The time complexity of the knapsack problem is as follows: Given a directed graph G = (V, E ), where each edge (v, w)
1. Without dynamic programing = O(2n) has a non-negative cost C[v, w], for all pairs of vertices (v,
2. With dynamic programing = O(mn) w), find the cost of the lowest-cost path from v to w. It is
a generalization of the single-sourceshortest-path problem.
It is one of the NPC problems.
4.10.1 Floyd’s Algorithm
4.9.4 Longest Common Subsequence
Let Ak(i, j) be the minimum cost required to go from
A subsequence of a given sequence is just the given sub- vertex i to vertex j for which all intermediate vertices are
sequence in which zero or more symbols are left out. in the set (0, 1, 2, 3, …, k) (Fig. 4.12).
Let sequence (S) = {A, B, B, A, B, B}, subsequence
1
(S1) = {A, A}, subsequence (S2) = {A, B, A, B} and
subsequence (S3) = {B, A, B, A}. 2
i j
4.9.4.1 Common Subsequence
LCS(i, j)
4.11.1 P-Complexity Class
0, if i = 0 or j = 0
= 1 + LCS(i - 1, j - 1), if X[i] = Y [ j ] P in computational complexity theory is known as poly-
nomial time or deterministic time. This is the most basic
Max[{LCS(i - 1, j)}{LCS(i, j - 1)}], if X[i] ≠ Y [ j ]
complexity class. This consists of all the problems that
are solvable in polynomial time. These problems can be 5. Subgraph isomorphism problem
solved in O(nk) time, where k is some constant. In class 6. Subset sum problem
P, problems are efficiently solvable or traceable. 7. Clique problem
A language L is in class P iff there exists some Turing 8. Vertex cover problem
machine M such that: 9. Independent set problem
10. Dominating set problem
1. Turing machine runs in polynomial time for all the 11. Graph colouring problem
inputs.
2. For all y in L, M must return 1, otherwise 0. 4.11.4 NP-Hard
P includes many natural problems like linear programming,
finding maximum matching and calculating the greatest NP-hard is a class that includes problems which are “at
common divisor. Prime number is also a part of class P now. least as hard as hardest problem in NP”. A problem is
said to be NP hard if
IMPORTANT FORMULAS
8. Binary search: Q(log n). 22. Dijkstra’s algorithm: O(E log V).
SOLVED EXAMPLES