We have introduced Graph implementation using array of vectors in Graph implementation using STL for competitive programming | Set 1. In this post, a different implementation is used which can be used to implement graphs using sets. The implementation is for adjacency list representation of graph.

A set is different from a vector in two ways: it stores elements in a sorted way, and duplicate elements are not allowed. Therefore, this approach cannot be used for graphs containing parallel edges. Since sets are internally implemented as binary search trees, **an edge between two vertices can be searched in O(logV) time**, where V is the number of vertices in the graph.

Following is an example of an undirected and unweighted graph with 5 vertices.

Below is adjacency list representation of this graph using array of sets.

Below is the code for adjacency list representation of an undirected graph using sets:

`// A C++ program to demonstrate adjacency list ` `// representation of graphs using sets ` `#include <bits/stdc++.h> ` `using` `namespace` `std; ` ` ` `struct` `Graph { ` ` ` `int` `V; ` ` ` `set<` `int` `, greater<` `int` `> >* adjList; ` `}; ` ` ` `// A utility function that creates a graph of V vertices ` `Graph* createGraph(` `int` `V) ` `{ ` ` ` `Graph* graph = ` `new` `Graph; ` ` ` `graph->V = V; ` ` ` ` ` `// Create an array of sets representing ` ` ` `// adjacency lists. Size of the array will be V ` ` ` `graph->adjList = ` `new` `set<` `int` `, greater<` `int` `> >[V]; ` ` ` ` ` `return` `graph; ` `} ` ` ` `// Adds an edge to an undirected graph ` `void` `addEdge(Graph* graph, ` `int` `src, ` `int` `dest) ` `{ ` ` ` `// Add an edge from src to dest. A new ` ` ` `// element is inserted to the adjacent ` ` ` `// list of src. ` ` ` `graph->adjList[src].insert(dest); ` ` ` ` ` `// Since graph is undirected, add an edge ` ` ` `// from dest to src also ` ` ` `graph->adjList[dest].insert(src); ` `} ` ` ` `// A utility function to print the adjacency ` `// list representation of graph ` `void` `printGraph(Graph* graph) ` `{ ` ` ` `for` `(` `int` `i = 0; i < graph->V; ++i) { ` ` ` `set<` `int` `, greater<` `int` `> > lst = graph->adjList[i]; ` ` ` `cout << endl << ` `"Adjacency list of vertex "` ` ` `<< i << endl; ` ` ` ` ` `for` `(` `auto` `itr = lst.begin(); itr != lst.end(); ++itr) ` ` ` `cout << *itr << ` `" "` `; ` ` ` `cout << endl; ` ` ` `} ` `} ` ` ` `// Searches for a given edge in the graph ` `void` `searchEdge(Graph* graph, ` `int` `src, ` `int` `dest) ` `{ ` ` ` `auto` `itr = graph->adjList[src].find(dest); ` ` ` `if` `(itr == graph->adjList[src].end()) ` ` ` `cout << endl << ` `"Edge from "` `<< src ` ` ` `<< ` `" to "` `<< dest << ` `" not found."` ` ` `<< endl; ` ` ` `else` ` ` `cout << endl << ` `"Edge from "` `<< src ` ` ` `<< ` `" to "` `<< dest << ` `" found."` ` ` `<< endl; ` `} ` ` ` `// Driver code ` `int` `main() ` `{ ` ` ` `// Create the graph given in the above figure ` ` ` `int` `V = 5; ` ` ` `struct` `Graph* graph = createGraph(V); ` ` ` `addEdge(graph, 0, 1); ` ` ` `addEdge(graph, 0, 4); ` ` ` `addEdge(graph, 1, 2); ` ` ` `addEdge(graph, 1, 3); ` ` ` `addEdge(graph, 1, 4); ` ` ` `addEdge(graph, 2, 3); ` ` ` `addEdge(graph, 3, 4); ` ` ` ` ` `// Print the adjacency list representation of ` ` ` `// the above graph ` ` ` `printGraph(graph); ` ` ` ` ` `// Search the given edge in the graph ` ` ` `searchEdge(graph, 2, 1); ` ` ` `searchEdge(graph, 0, 3); ` ` ` ` ` `return` `0; ` `} ` |

*chevron_right*

*filter_none*

Output:

Adjacency list of vertex 0 4 1 Adjacency list of vertex 1 4 3 2 0 Adjacency list of vertex 2 3 1 Adjacency list of vertex 3 4 2 1 Adjacency list of vertex 4 3 1 0 Edge from 2 to 1 found. Edge from 0 to 3 not found.

*Pros*: Queries like whether there is an edge from vertex u to vertex v can be done in O(log V).

*Cons*:

- Adding an edge takes O(log V), as opposed to O(1) in vector implementation.
- Graphs containing parallel edge(s) cannot be implemented through this method.

**Further Optimization of Edge Search Operation using unordered_set (or hashing): **

The edge search operation can be further optimized to O(1) using unordered_set which uses hashing internally.

`// A C++ program to demonstrate adjacency list ` `// representation of graphs using sets ` `#include <bits/stdc++.h> ` `using` `namespace` `std; ` ` ` `struct` `Graph { ` ` ` `int` `V; ` ` ` `unordered_set<` `int` `>* adjList; ` `}; ` ` ` `// A utility function that creates a graph of ` `// V vertices ` `Graph* createGraph(` `int` `V) ` `{ ` ` ` `Graph* graph = ` `new` `Graph; ` ` ` `graph->V = V; ` ` ` ` ` `// Create an array of sets representing ` ` ` `// adjacency lists. Size of the array will be V ` ` ` `graph->adjList = ` `new` `unordered_set<` `int` `>[V]; ` ` ` ` ` `return` `graph; ` `} ` ` ` `// Adds an edge to an undirected graph ` `void` `addEdge(Graph* graph, ` `int` `src, ` `int` `dest) ` `{ ` ` ` `// Add an edge from src to dest. A new ` ` ` `// element is inserted to the adjacent ` ` ` `// list of src. ` ` ` `graph->adjList[src].insert(dest); ` ` ` ` ` `// Since graph is undirected, add an edge ` ` ` `// from dest to src also ` ` ` `graph->adjList[dest].insert(src); ` `} ` ` ` `// A utility function to print the adjacency ` `// list representation of graph ` `void` `printGraph(Graph* graph) ` `{ ` ` ` `for` `(` `int` `i = 0; i < graph->V; ++i) { ` ` ` `unordered_set<` `int` `> lst = graph->adjList[i]; ` ` ` `cout << endl << ` `"Adjacency list of vertex "` ` ` `<< i << endl; ` ` ` ` ` `for` `(` `auto` `itr = lst.begin(); itr != lst.end(); ++itr) ` ` ` `cout << *itr << ` `" "` `; ` ` ` `cout << endl; ` ` ` `} ` `} ` ` ` `// Searches for a given edge in the graph ` `void` `searchEdge(Graph* graph, ` `int` `src, ` `int` `dest) ` `{ ` ` ` `auto` `itr = graph->adjList[src].find(dest); ` ` ` `if` `(itr == graph->adjList[src].end()) ` ` ` `cout << endl << ` `"Edge from "` `<< src ` ` ` `<< ` `" to "` `<< dest << ` `" not found."` ` ` `<< endl; ` ` ` `else` ` ` `cout << endl << ` `"Edge from "` `<< src ` ` ` `<< ` `" to "` `<< dest << ` `" found."` ` ` `<< endl; ` `} ` ` ` `// Driver code ` `int` `main() ` `{ ` ` ` `// Create the graph given in the above figure ` ` ` `int` `V = 5; ` ` ` `struct` `Graph* graph = createGraph(V); ` ` ` `addEdge(graph, 0, 1); ` ` ` `addEdge(graph, 0, 4); ` ` ` `addEdge(graph, 1, 2); ` ` ` `addEdge(graph, 1, 3); ` ` ` `addEdge(graph, 1, 4); ` ` ` `addEdge(graph, 2, 3); ` ` ` `addEdge(graph, 3, 4); ` ` ` ` ` `// Print the adjacency list representation of ` ` ` `// the above graph ` ` ` `printGraph(graph); ` ` ` ` ` `// Search the given edge in the graph ` ` ` `searchEdge(graph, 2, 1); ` ` ` `searchEdge(graph, 0, 3); ` ` ` ` ` `return` `0; ` `} ` |

*chevron_right*

*filter_none*

Output :

Adjacency list of vertex 0 4 1 Adjacency list of vertex 1 4 3 2 0 Adjacency list of vertex 2 3 1 Adjacency list of vertex 3 4 2 1 Adjacency list of vertex 4 3 1 0 Edge from 2 to 1 found. Edge from 0 to 3 not found.

*Pros*:

- Queries like whether there is an edge from vertex u to vertex v can be done in O(1).
- Adding an edge takes O(1).

*Cons*:

- Graphs containing parallel edge(s) cannot be implemented through this method.
- Edges are not stored in any order.

**Note :** **adjacency matrix representation** is the most optimized for edge search, but space requirements of adjacency matrix are comparatively high for big sparse graphs. Moreover adjacency matrix has other disadvantages as well like BFS and DFS become costly as we can’t quickly get all adjacent of a node.

This article is contributed by **vaibhav29498**. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the **DSA Self Paced Course** at a student-friendly price and become industry ready.

## Recommended Posts:

- Graph and its representations
- What are Hash Functions and How to choose a good Hash Function?
- Check if binary representations of 0 to N are present as substrings in given binary string
- Sort elements by frequency | Set 4 (Efficient approach using hash)
- Overview of Data Structures | Set 2 (Binary Tree, BST, Heap and Hash)
- Sorting using trivial hash function
- String hashing using Polynomial rolling hash function
- Advantages of BST over Hash Table
- Implementing our Own Hash Table with Separate Chaining in Java
- Hash Table vs STL Map
- Implementing own Hash Table with Open Addressing Linear Probing in C++
- MD5 hash in Java
- Hash Function for String data in C#
- Cryptographic Hash Function in Java
- Count of unique lengths of connected components for an undirected graph using STL
- Mathematics | Graph Theory Basics - Set 2
- Add and Remove Edge in Adjacency Matrix representation of a Graph
- Breadth First Search or BFS for a Graph
- Depth First Search or DFS for a Graph
- Transpose graph