我们在使用 STL 进行竞争性编程的 Graph 实现中介绍了使用向量数组的 Graph 实现 |集合 1。在这篇文章中,使用了一个不同的实现,它可以使用集合来实现图。该实现用于图的邻接列表表示。
集合与向量有两点不同:它以有序的方式存储元素,不允许重复元素。因此,这种方法不能用于包含平行边的图。由于集合在内部实现为二叉搜索树,因此可以在 O(logV) 时间内搜索两个顶点之间的边,其中 V 是图中的顶点数。 Python中的集合是无序的,没有索引。因此,对于Python,我们将使用字典,它将源顶点作为键,其邻接列表将以设置格式存储为该键的值。
以下是具有 5 个顶点的无向和未加权图的示例。
下面是使用集合数组的此图的邻接列表表示。
下面是使用集合的无向图的邻接表表示的代码:
C++
// A C++ program to demonstrate adjacency list
// representation of graphs using sets
#include
using namespace std;
struct Graph {
int V;
set >* 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 >[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 > 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;
}
Java
// A Java program to demonstrate adjacency
// list using HashMap and TreeSet
// representation of graphs using sets
import java.util.*;
class Graph{
// TreeSet is used to get clear
// understand of graph.
HashMap> graph;
static int v;
// Graph Constructor
public Graph()
{
graph = new HashMap<>();
for(int i = 0; i < v; i++)
{
graph.put(i, new TreeSet<>());
}
}
// Adds an edge to an undirected graph
public void addEdge(int src, int dest)
{
// Add an edge from src to dest into the set
graph.get(src).add(dest);
// Since graph is undirected, add an edge
// from dest to src into the set
graph.get(dest).add(src);
}
// A utility function to print the graph
public void printGraph()
{
for(int i = 0; i < v; i++)
{
System.out.println("Adjacency list of vertex " + i);
Iterator set = graph.get(i).iterator();
while (set.hasNext())
System.out.print(set.next() + " ");
System.out.println();
System.out.println();
}
}
// Searches for a given edge in the graph
public void searchEdge(int src, int dest)
{
Iterator set = graph.get(src).iterator();
if (graph.get(src).contains(dest))
System.out.println("Edge from " + src + " to " +
dest + " found");
else
System.out.println("Edge from " + src + " to " +
dest + " not found");
System.out.println();
}
// Driver code
public static void main(String[] args)
{
// Create the graph given in the above figure
v = 5;
Graph graph = new Graph();
graph.addEdge(0, 1);
graph.addEdge(0, 4);
graph.addEdge(1, 2);
graph.addEdge(1, 3);
graph.addEdge(1, 4);
graph.addEdge(2, 3);
graph.addEdge(3, 4);
// Print the adjacency list representation of
// the above graph
graph.printGraph();
// Search the given edge in the graph
graph.searchEdge(2, 1);
graph.searchEdge(0, 3);
}
}
// This code is contributed by rexj8
Python3
# Python3 program to represent adjacency
# list using dictionary
class graph(object):
def __init__(self, v):
self.v = v
self.graph = dict()
# Adds an edge to undirected graph
def addEdge(self, source, destination):
# Add an edge from source to destination.
# If source is not present in dict add source to dict
if source not in self.graph:
self.graph = {destination}
else:
self.graph.add(destination)
# Add an dge from destination to source.
# If destination is not present in dict add destination to dict
if destination not in self.graph:
self.graph[destination] = {source}
else:
self.graph[destination].add(source)
# A utility function to print the adjacency
# list representation of graph
def print(self):
for i, adjlist in sorted(self.graph.items()):
print("Adjacency list of vertex ", i)
for j in sorted(adjlist, reverse = True):
print(j, end = " ")
print('\n')
# Search for a given edge in graph
def searchEdge(self,source,destination):
if source in self.graph:
if destination in self.graph:
if destination in self.graph:
if source in self.graph[destination]:
print("Edge from {0} to {1} found.\n".format(source, destination))
return
else:
print("Edge from {0} to {1} not found.\n".format(source, destination))
return
else:
print("Edge from {0} to {1} not found.\n".format(source, destination))
return
else:
print("Destination vertex {} is not present in graph.\n".format(destination))
return
else:
print("Source vertex {} is not present in graph.\n".format(source))
# Driver code
if __name__=="__main__":
g = graph(5)
g.addEdge(0, 1)
g.addEdge(0, 4)
g.addEdge(1, 2)
g.addEdge(1, 3)
g.addEdge(1, 4)
g.addEdge(2, 3)
g.addEdge(3, 4)
# Print adjacenecy list
# representation of graph
g.print()
# Search the given edge in a graph
g.searchEdge(2, 1)
g.searchEdge(0, 3)
#This code is contributed by Yalavarthi Supriya
Javascript
C++
// A C++ program to demonstrate adjacency list
// representation of graphs using sets
#include
using namespace std;
struct Graph {
int V;
unordered_set* 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[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 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;
}
输出
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.
优点:诸如从顶点 u 到顶点 v 是否存在边的查询可以在 O(log V) 中完成。
缺点:
- 添加一条边需要 O(log V),而不是向量实现中的 O(1)。
- 无法通过此方法实现包含平行边的图。
使用 unordered_set(或散列)进一步优化边缘搜索操作:
边缘搜索操作可以使用内部使用散列的 unordered_set 进一步优化为 O(1)。
C++
// A C++ program to demonstrate adjacency list
// representation of graphs using sets
#include
using namespace std;
struct Graph {
int V;
unordered_set* 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[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 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;
}
输出
Adjacency list of vertex 0
4 1
Adjacency list of vertex 1
4 3 0 2
Adjacency list of vertex 2
3 1
Adjacency list of vertex 3
4 1 2
Adjacency list of vertex 4
3 0 1
Edge from 2 to 1 found.
Edge from 0 to 3 not found.
优点:
- 诸如从顶点 u 到顶点 v 是否存在边的查询可以在 O(1) 中完成。
- 添加一条边需要 O(1)。
缺点:
- 无法通过此方法实现包含平行边的图。
- 边以任何顺序存储。
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。