Chapter-3 Greedy Algorithm
Chapter-3 Greedy Algorithm
• It doesn't worry whether the current best result will bring the overall
optimal result.
• The algorithm never reverses the earlier decision even if the choice is
wrong. It works in a top-down approach.
• This algorithm may not produce the best result for all the problems.
It's because it always goes for the local best choice to produce the
global best result.
2. Optimal Substructure
• If the optimal overall solution to the problem corresponds to the
optimal solution to its subproblems, then the problem can be solved
using a greedy approach.
Greedy Approach
1.Let's start with the root node 20. The weight of the right child
is 3 and the weight of the left child is 2.
2. Our problem is to find the largest path. And, the optimal solution at
the moment is 3. So, the greedy algorithm will choose 3.
Longest path
Therefore, greedy algorithms do not always give an optimal/feasible
solution.
Greedy Algorithm
To begin with, the solution set (containing answers) is empty.
At each step, an item is added to the solution set until a solution is
reached.
If the solution set is feasible, the current item is kept.
Else, the item is rejected and never considered again.
Let's now use this algorithm to solve a problem.
Example - Greedy Approach
Problem: You have to make a change of an amount using the smallest possible number
of coins.
Amount: $18
Available coins are
$5 coin
$2 coin
$1 coin
There is no limit to the number of each coin you can use.
Solution:
Spanning tree
Huffman Coding
Dijkstra's Algorithm
Spanning Tree and Minimum Spanning Tree
Undirected Graph
Spanning Tree and Minimum Spanning Tree
• A connected graph is a graph in which there is always a path from a vertex
to any other vertex.
Connected graph
Spanning tree
• A spanning tree is a sub-graph of an undirected connected graph, which
includes all the vertices of the graph with a minimum possible number of
edges.
• If a vertex is missed, then it is not a spanning tree.
• The edges may or may not have weights assigned to them.
Spanning tree
• The total number of spanning trees with n vertices that can be created
from a complete graph is equal to n(n-2).
• If we have n = 4, the maximum number of possible spanning trees is
equal to 44-2 = 16. Thus, 16 spanning trees can be formed from a
complete graph with 4 vertices.
Example of a Spanning Tree
Let's understand the spanning tree with examples below:
Let the original graph be:
Normal graph
Spanning tree
• Some of the possible spanning trees that can be created from
the above graph are:
Minimum Spanning Tree
• A minimum spanning tree is a spanning tree in which the sum of
the weight of the edges is as minimum as possible.
Example of a Spanning Tree
• Let's understand the above definition with the help of the example
below.
• The initial graph is:
Weighted graph
Cluster Analysis
electrical grids.
Prim's Algorithm
Prim's algorithm is a minimum spanning tree algorithm that takes a graph as
input and finds the subset of the edges of that graph which
Form a tree that includes every vertex
Has the minimum sum of weights among all the trees that can be formed
from the graph
How Prim's algorithm works
It falls under a class of algorithms called greedy algorithms that find the local
optimum in the hopes of finding a global optimum.
We start from one vertex and keep adding edges with the lowest weight until
we reach our goal.
The steps for implementing Prim's algorithm are as follows:
Initialize the minimum spanning tree with a vertex chosen at random.
Find all the edges that connect the tree to new vertices, find the minimum and
add it to the tree
Keep repeating step 2 until we get a minimum spanning tree
Example of Prim's algorithm
Steps
Example of Prim's algorithm: steps
random
Example of Prim's algorithm: steps
• Instead of starting from a vertex, Kruskal's algorithm sorts all the edges
from low weight to high and keeps adding the lowest edges, ignoring those
edges that create a cycle.
Prim's Algorithm Complexity
Initial string
How Huffman Coding works?
• Each character occupies 8 bits. There are a total of 15 characters in the
above string. Thus, a total of 8 * 15 = 120 bits are required to send this
string.
• Huffman coding first creates a tree using the frequencies of the character
and then generates code for each character.
• Once the data is encoded, it has to be decoded. Decoding is done using the
same tree.
• Huffman Coding prevents any ambiguity in the decoding process using the
concept of prefix code i.e. a code associated with a character should not
be present in the prefix of any other code. The tree created above helps in
maintaining the property.
How Huffman Coding works?
Huffman coding is done with the help of the following steps.
1.Calculate the frequency of each character in the string.
Frequency of string
2. Sort the characters in increasing order of the frequency. These are stored
in a priority queue Q.
• For each non-leaf node, assign 0 to the left edge and 1 to the right edge.
A 5 11 5*2 = 10
B 1 100 1*3 = 3
C 6 0 6*1 = 6
D 3 101 3*3 = 9
Without encoding, the total size of the string was 120 bits. After encoding
the size is reduced to 32 + 15 + 28 = 75
.
How Huffman Coding works?
Decoding the code
•For decoding the code, we can take the code and traverse through the
tree to find the character.
•Let 101 is to be decoded, we can traverse from the root as in the figure
below.
Huffman Coding Algorithm
• The time complexity for encoding each unique character based on its
frequency is O(nlog n).
Then we visit each node and its neighbors to find the shortest subpath to
those neighbors.
The algorithm uses a greedy approach in the sense that we find the next
best solution hoping that the end result is the best solution for the whole
problem.
Example of Dijkstra's algorithm
s
Example of Dijkstra's algorithm
Example of Dijkstra's algorithm
Example of Dijkstra's algorithm
Djikstra's algorithm pseudocode
• We need to maintain the path distance of every vertex. We can store
that in an array of size v, where v is the number of vertices.
• We also want to be able to get the shortest path, not only know the
length of the shortest path. For this, we map each vertex to the vertex
that last updated its path length.
function dijkstra(G, S)
for each vertex V in G
distance[V] <- infinite
previous[V] <- NULL
If V != S, add V to Priority Queue Q
distance[S] <- 0