1. Home
Data Structure

Data Structure Tutorial: Everything You Need to Know

Learn all about data structures with our comprehensive tutorial. Master the fundamentals and advance your skills in organizing and managing data efficiently.

  • 60
  • 14
right-top-arrow

Tutorial Playlist

58 Lessons
36

Exploring the Power and Potential of Greedy Algorithms in Data Structures

Updated on 12/08/2024448 Views

Introduction

In computer science and algorithm design, efficiency and optimality are paramount objectives. Greedy algorithms represent a fundamental approach to solving optimization problems by making locally optimal choices at each step with the hope of finding a globally optimal solution. Rooted in the principle of selecting the best immediate option without regard to future consequences, greedy algorithms offer an intuitive and often efficient method for tackling a variety of computational challenges.

Overview

Greedy algorithms represent a powerful paradigm in computer science, particularly in the context of data structures. These algorithms operate on the principle of making locally optimal choices at each step, with the expectation that such choices will lead to a globally optimal solution. 

Greedy algorithms find widespread application due to their simplicity, efficiency, and effectiveness in solving various optimization problems. 

This tutorial delves into the fundamentals of greedy algorithms within the context of data structures. It explores the key characteristics and properties that define greedy algorithms, including their greedy choice property and optimal substructure property. 

What is a Greedy Algorithm

Greedy algorithms are a class of algorithms that make locally optimal choices at each step with the hope of finding a globally optimal solution. They follow a simple heuristic approach, where they select the best immediate choice without considering the consequences of that choice in the long term. 

Greedy algorithms are characterized by two key properties:

1. Greedy Choice Property: At each step of the algorithm, a greedy choice is made by selecting the best available option without considering its consequences for future steps. This means that the choice made at each step appears to be the best option at that particular moment.

2. Optimal Substructure Property: The problem can be broken down into smaller subproblems, and the solution to the overall problem can be constructed by combining optimal solutions to these subproblems.

Example:

Consider the problem of finding the minimum spanning tree (MST) of a graph. A minimum spanning tree is a subgraph of the original graph that is a tree (connected and acyclic) and spans all the vertices of the original graph while minimizing the total edge weight.

One greedy algorithm for finding the MST of a graph is Prim's Algorithm. Prim's Algorithm starts with an arbitrary vertex as the initial tree and repeatedly grows the tree by adding the cheapest edge that connects a vertex in the tree to a vertex outside the tree. At each step, the algorithm selects the cheapest available edge that connects a vertex in the tree to a vertex outside the tree. This process continues until all vertices are included in the tree, resulting in a minimum-spanning tree.

Characteristics Illustrated with an Example:

Greedy Choice Property: In Prim's Algorithm, at each step, the algorithm selects the cheapest available edge that connects a vertex in the tree to a vertex outside the tree.

Optimal Substructure Property: The problem of finding the minimum-spanning tree exhibits optimal substructure because the MST of the entire graph can be constructed from the MSTs of its smaller subgraphs. Prim's Algorithm adds edges to the growing tree, ensuring that the resulting tree is always a minimum-spanning tree.

Importance of Greedy Algorithms

Greedy algorithms play a crucial role in algorithm design due to their simplicity, efficiency, and effectiveness in solving optimization problems. They find extensive applications in various domains, especially in data structures, where they offer elegant solutions to a wide range of computational challenges.

Example: Dijkstra's Algorithm for Shortest Path

Dijkstra's Algorithm is a classic example of a greedy algorithm used to find the shortest path between nodes in a weighted graph. It operates by iteratively selecting the vertex with the shortest known distance from the source vertex and updating the distances of its neighboring vertices accordingly.

Output: 0 4 12 19 21 11 9 8 14

Explanation: 

The distance from 0 to 1 = 4.
The minimum distance from 0 to 2 = 12. 0->1->2
The minimum distance from 0 to 3 = 19. 0->1->2->3
The minimum distance from 0 to 4 = 21. 0->7->6->5->4
The minimum distance from 0 to 5 = 11. 0->7->6->5
The minimum distance from 0 to 6 = 9. 0->7->6
The minimum distance from 0 to 7 = 8. 0->7
The minimum distance from 0 to 8 = 14. 0->1->2->8

Basic Concepts of Greedy Algorithms:

A. Greedy Choice Property:

The greedy choice property states that at each step of the algorithm, a greedy choice is made by selecting the best available option without considering the consequences of that choice on future steps. This means that the choice made at each step appears to be the best option at that particular moment.

Example: Coin Change Problem

Consider the coin change problem, where you must change a given amount using the fewest possible coins. Suppose you have coins of denominations 1, 5, and 10. The greedy approach would always be to select the largest denomination coin that is less than or equal to the remaining amount at each step.

B. Optimal Substructure Property:

The optimal substructure property states that the problem being solved by the greedy algorithm exhibits optimal substructure if an optimal solution to the problem can be constructed from optimal solutions to its subproblems. In other words, the problem can be broken down into smaller subproblems, and the solution to the overall problem can be constructed by combining optimal solutions to these subproblems.

Example: Activity Selection Problem

Consider the activity selection problem, where you are given a set of activities, each with a start time and an end time, and you want to select the maximum number of non-overlapping activities. The greedy approach to this problem involves selecting activities based on their finish times.

C. Greedy Algorithms and Optimal Solutions:

Despite their simplicity and efficiency, greedy algorithms do not always guarantee optimal solutions for every problem. However, they often provide approximate solutions sufficiently close to the optimal solution, especially for issues with greedy choice and optimal substructure properties.

The basic concepts of greedy algorithms—greedy choice property, optimal substructure property, and their relationship with optimal solutions—illustrate the principles underlying their operation and effectiveness in efficiently solving optimization problems.

Types of Greedy Algorithms

A. Minimum Spanning Tree (MST) Algorithms:

1. Prim's Algorithm

2. Kruskal's Algorithm

Kruskal's Algorithm is a greedy algorithm used to find the minimum spanning tree (MST) of a connected, undirected graph. It operates by iteratively adding edges to the growing MST while ensuring no cycles are formed. The algorithm selects edges in a non-decreasing order of their weights.

Example: Minimum Spanning Tree

Consider a weighted graph representing a network of cities with roads connecting them. Each edge has a weight indicating the distance between the cities. The goal is to find the minimum spanning tree (MST) of this graph.

B. Shortest Path Algorithms:

1. Dijkstra's Algorithm

2. Bellman-Ford Algorithm

The Bellman-Ford Algorithm is a classic dynamic programming algorithm used to find the shortest paths from a single source vertex to all other vertices in a weighted graph, even in negative edge weights and negative weight cycles. While Bellman-Ford is not inherently a greedy algorithm, modifications can be made to its approach to make it more greedy.

Example: Shortest Path

Consider a weighted graph representing a network of cities with roads connecting them, where each edge has a weight indicating the distance between the cities. The goal is to find the shortest path from a given source vertex to all other vertices in the graph.

C. Huffman Coding:

Huffman Coding is a widely used algorithm for lossless data compression. A variable-length prefix coding algorithm assigns shorter codes to more frequent symbols and longer codes to less frequent symbols, thereby achieving compression by representing the most common symbols with fewer bits.

To build a Huffman Tree:

1. Create leaf nodes for each unique character with their frequency of occurrences.
2. Build a min heap (priority queue) of all leaf nodes, where the least frequent character is at the root.
3. Repeat until the heap has only one node:
a. Extract two nodes with the minimum frequency.
b. Create a new internal node with a frequency equal to the sum of the frequencies of the extracted nodes. Set the extracted nodes as their children.
c. Add the new internal node to the min heap.
4. The remaining node in the heap is the root node, and the Huffman Tree is complete.
For example:
Character | Frequency
a 5
b 9
c 12
d 13
e 16
f 45

Illustration of steps:

1. Create a min heap with six nodes, each representing a single-character tree.

2. Extract two minimum frequency nodes, create an internal node with frequency 14, and add it to the heap.

3. Repeat: extract, combine, and add nodes until one node remains in the heap.

4. The final heap contains the root node with a frequency of 100.

To print codes from the Huffman Tree:

Traverse the tree from the root, maintaining an auxiliary array.

While moving left, append 0 to the array; while moving right, append 1.

Print the array when reaching a leaf node.

The resulting codes for characters are:

Character | Code-word

f 0
c 100
d 101
a 1100
b 1101
e 111

D. Fractional Knapsack Problem (or Greedy Algorithm for Knapsack Problem or Knapsack Problem using greedy method example)

The Fractional Knapsack Problem is a classic optimization problem in which items of different weights and values must be placed into a knapsack of limited capacity to maximize their total value. 

This Problem aims to maximize the total profit by selecting items, given their weights and profits, to fit into a knapsack of capacity W. It allows breaking items to optimize the total value.

Input: arr[] = {{60, 10}, {100, 20}, {120, 30}}, W = 50

Output: 240

Explanation: Select items of weights 10 and 20 kg and 2/3 fraction of the 30 kg item.

Total profit: 60+100+(2/3)(120) = 240

Input: arr[] = {{500, 30}}, W = 10

Output: 166.667

To solve this problem efficiently using the Greedy approach:

1. Calculate the profit-to-weight ratio for each item and sort the items accordingly.

2. Iterate through the sorted items:
a. If the item's weight exceeds the remaining capacity, add its profit to the result.
b. If the weight exceeds the remaining capacity, add a fraction of the item that fits and break the loop.

3. Return the total profit obtained.

Illustration:

Consider arr[] = {{100, 20}, {60, 10}, {120, 30}}, W = 50.

Sorting the array based on profit-to-weight ratio: {{60, 10}, {100, 20}, {120, 30}}.

Iteration:

- Add item with weight 10 (profit 60) to knapsack. Remaining W = 40.
- Add item with weight 20 (profit 100) to knapsack. Remaining W = 20.
- Add 2/3 fraction of the item with weight 30 (profit 120) to knapsack. Remaining W = 0.
Total profit: 240.

Steps to solve:
1. Calculate the profit/weight ratio for each item.
2. Sort items in decreasing order of the ratio.
3. Initialize result = 0 and current capacity = given capacity.
4. Iterate through sorted items:
-If weight <= remaining capacity, add profit to the result.
- Otherwise, add a fraction of the item and break.
Return result.

An example of a Greedy Algorithm is explained above in “Coin Change Problem” under “Basic Concepts of Greedy Algorithms”.

Greedy Search Algorithm

Greedy search is not a standard algorithm in the same way that, say, Dijkstra's or A* are. Rather, "greedy search" refers to a general strategy used in various algorithms.

A greedy search algorithm is a technique where, at each step, the algorithm makes the locally optimal choice with the hope that this will lead to a globally optimal solution. It works by selecting the best option at each decision point without considering the overall consequences.

Example:

Suppose you want to find the shortest path from point A to point B in a city grid. A greedy search approach might involve always choosing the path that appears to be the shortest at each intersection without considering the overall length of the path.

Conclusion

Greedy algorithms in data structures offer an efficient and straightforward approach to solving various optimization problems. These algorithms often provide fast solutions to complex issues by making locally optimal choices at each step. However, their simplicity comes with a trade-off, as they may not always guarantee the globally optimal solution. Nonetheless, their versatility and effectiveness make them a valuable tool in various domains, from network algorithms to data compression and beyond. Understanding their strengths and limitations is vital to leveraging them effectively in problem-solving scenarios.

FAQs

1. Why is it called a greedy algorithm?

It's called a greedy algorithm because it makes the locally optimal choice at each step, hoping that this will lead to a globally optimal solution.

2. Where is a greedy algorithm used?

Greedy algorithms are used in optimization problems, network algorithms, data compression, approximation algorithms, and routing algorithms due to their simplicity and efficiency.

3. Are there cases where greedy algorithms fail to find the optimal solution?

Yes. While greedy algorithms can provide optimal or near-optimal solutions for many problems, they may not yield the best possible outcome in some cases. This is especially true for problems that don't exhibit the optimal substructure property.

Abhimita Debnath

Abhimita Debnath

Abhimita Debnath is one of the students in UpGrad Big Data Engineering program with BITS Pilani. She's a Senior Software Engineer in Infosys. She…Read More

Get Free Career Counselling
form image
+91
*
By clicking, I accept theT&Cand
Privacy Policy
image
right-top-arrowleft-top-arrow

upGrad Learner Support

Talk to our experts. We’re available 24/7.

text

Indian Nationals

1800 210 2020

text

Foreign Nationals

+918045604032

Disclaimer

upGrad does not grant credit; credits are granted, accepted or transferred at the sole discretion of the relevant educational institution offering the diploma or degree. We advise you to enquire further regarding the suitability of this program for your academic, professional requirements and job prospects before enr...