简体   繁体   English

在 C++ 中将邻接列表转换为有向无环图的邻接矩阵

[英]Converting an Adjacency List to a an Adjacency Matrix for a Directed Acyclic Graph in C++

I was trying to implement topological sort in C++ using DFS but I got stuck with the conversion of an adjacency list to an adjacency matrix for the purpose.我试图在 C++ 中使用 DFS 实现拓扑排序,但出于此目的,我坚持将邻接列表转换为邻接矩阵。 The problem I am encountering is that for a DAG every node might not have an outgoing edge so I can't simply create an adjacency list with a function like this which is valid for an undirected graph:-我遇到的问题是,对于 DAG,每个节点可能没有传出边,所以我不能简单地使用 function 创建一个邻接列表,这对于无向图有效:-

void addEdge(list <int> l,int u,int v)
{
        l[u].push_back(v);
        l[v].push_back(u);
}

So it would be of great help if you could provide a way to implement an adjacency list for a DAG and suggest the code to convert it into an adjacency matrix.因此,如果您可以提供一种为 DAG 实现邻接列表的方法并建议将其转换为邻接矩阵的代码,那将是非常有帮助的。 An implementation avoiding the use of structs and classes is highly appreciated.高度赞赏避免使用结构和类的实现。

You would only require to add a single edge in that case.在这种情况下,您只需要添加一条边。

void addEdge (vector <list <int>> l, int u, int v)
{
    l[u].emplace_back (v); // u directs to v 
}

Run this function for all the edge pairs, and your adjacency list l will be completed.对所有边对运行此 function,您的邻接列表l将完成。

Now, create an adjacency matrix as a square 2D array, initialising all the elements initially to 0 .现在,将邻接矩阵创建为方形 2D 数组,将所有元素初始初始化为0

int mat[V][V] = {}; // V is the total number of vertices in the graph 

Now, simply traverse the adjacency list and for every edge (u, v) , set mat[u][v] = 1 , denoting that vertex u directs to vertex v .现在,简单地遍历邻接表并为每条边(u, v)设置mat[u][v] = 1 ,表示顶点u指向顶点v

for (int u = 0; u < V; ++u)
    for (auto v: l[u])
        mat[u][v] = 1;

Make sure that l has memory allocated beforehand till atleast V elements so as to not get a Segmentation Fault:确保l预先分配了 memory 直到至少V个元素,以免出现分段错误:

vector <list <int>> l(V);

Actually you can implement DFS (and so the topological sort) in terms of an adjacency list.实际上,您可以根据邻接列表来实现 DFS(以及拓扑排序)。 In fact, adjacency list is the most efficient way to represent a graph for DFS (see below).事实上,邻接表是表示 DFS 图形的最有效方式(见下文)。

All you need for DFS is an ability to see, which vertices are adjacent to the current vertex: DFS 所需要的只是查看哪些顶点与当前顶点相邻的能力:

vector<list<int>> graph;
vector<bool> visited;

void dfs(int current) {
  visited[current] = true;

  // iterating over adjacent vertices
  for (int other : graph[current])
    if (not visited[other])
      dfs(other);
}

So your topological sort can look something like this:所以你的拓扑排序看起来像这样:

enum class status { unseen, entered, left };

vector<list<int>> graph;
vector<status> visited;
vector<int> topsorted;

void topsort_impl_dfs(int current) {
  visited[current] = status::entered;

  // iterating over adjacent vertices
  for (int other : graph[current]) {
    if (visited[other] == status::unseen) {
      dfs(other);
    } else if (visited[other] == status::entered) {
      // found a loop, not a DAG
    }
    // ignoring vertices with status::left, because they're already processed
  }

  topsorted.push_back(current);
  visited[current] = status::left;
}

void topsort() {
  fill(visited.begin(), visited.end(), status::unseen);

  topsorted.clear();
  topsorted.reserve(VERTEX_COUNT);

  for (int v = 0; v < VERTEX_COUNT; ++v) {
    if (visited[v] == status::unseen) {
      topsort_impl_dfs(v);
    }
  }

  // vertices are added to topsorted in an inverse order
  reverse(topsorted.begin(), topsorted.end());
}

If we compare the implementation of DFS with adjacency matrix and list, there is what we get ( V is vertex count, E is edge count):如果我们将 DFS 的实现与邻接矩阵和列表进行比较,我们会得到( V是顶点数, E是边数):

  • for an adjacency matrix: in each call to dfs(v) (one call for each vertex, V in total) we will iterate over the corresponding matrix row ( V iterations).对于邻接矩阵:在对dfs(v)的每次调用(每个顶点一次调用,总共V )中,我们将遍历相应的矩阵行( V次迭代)。 So we get O(V*V) complexity.所以我们得到O(V*V)复杂度。

  • for an adjacency list: for every vertex we iterate only over the adjacent ones.对于邻接列表:对于每个顶点,我们只迭代相邻的顶点。 It is harder to analyze this from that perspective because vertices have different count of adjacent vertices.从这个角度分析这个更难,因为顶点有不同的相邻顶点数。 But we can look at it like this: for each vertex we iterate over all outgoing edges.但是我们可以这样看:对于每个顶点,我们遍历所有出边。 Each edge has exactly one start point, so, in total, we make exactly E iterations, and the complexity is O(E).每条边都有一个起点,因此,我们总共进行了E次迭代,复杂度为 O(E)。 It isn't worse than the first way, because in the worst case (full graph) we'll have E = O(V*V) .它并不比第一种方式更糟,因为在最坏的情况下(全图)我们将有E = O(V*V)

So if your graph has V=1000 E=1000 , then the second way will be ~1000 times faster.因此,如果您的图表有V=1000 E=1000 ,那么第二种方式将快约 1000 倍。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM