📜  使用集合和散列的图形表示

📅  最后修改于: 2021-10-27 07:10:44             🧑  作者: Mango

我们在使用 STL 进行竞争性编程的 Graph 实现中介绍了使用向量数组的 Graph 实现 |集合 1。在这篇文章中,使用了一个不同的实现,它可以使用集合来实现图。该实现用于图的邻接列表表示。

集合与向量有两点不同:它以有序的方式存储元素,不允许重复元素。因此,这种方法不能用于包含平行边的图。由于集合在内部实现为二叉搜索树,因此可以在 O(logV) 时间内搜索两个顶点之间的边,其中 V 是图中的顶点数。 Python中的集合是无序的,没有索引。因此,对于Python,我们将使用字典,它将源顶点作为键,其邻接列表将以设置格式存储为该键的值。

以下是具有 5 个顶点的无向和未加权图的示例。

8

下面是使用集合数组的此图的邻接列表表示。

9

下面是使用集合的无向图的邻接表表示的代码:

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 现场工作专业课程学生竞争性编程现场课程