简体   繁体   中英

Algorithm for efficient graph traversal

I am searching an algorithm or an idea for an algorithm for the following use case:

A directed graph consists of multiple vertices. Some of these vertices are annotated with a value (like a number) and have no parent vertices (predecessors). All other vertices are representing operations. An operation can be only performed if all annotated values of the parent vertices (predecessors) are known. The result or value of the operation is then stored in the vertex.

My solution idea:

  1. Store all vertices that have at least one parent vertex (predecessor) in a set
  2. While the set is not empty:
    1. Get the next vertex from the set
    2. Check if the value for all parent vertices (predecessors) are known
    3. If all values are known:
      1. Remove the vertex from the set
      2. Perform the operation
      3. Store the result of the operation in the vertex
      4. Loop (go to 2.)
    4. Else: Loop (go to 2.)

My problem: I think this solution idea could work but it is not efficient (especially for large graph structures).

Are there more efficient approaches to solve this problem?

There are some possibilities that avoid rechecking vertexes aimlessly, for example:

  1. Initialize an array of integers storing, for each vertex, the number of parents.
  2. Initialize a set of vertexes that have 0 parents (can be done at the same time as step 1).
  3. Until that set is empty:
    1. Take some vertex a from that set and process it.
    2. For every edge from a to a vertex b , decrement the parent-count of vertex b . If the count reaches 0, add b to the set of vertexes that are ready to process.

What want to do is called a 'topological sort' -- in the order in which you process the vertices, every node's predecessors must occur before it does: https://en.wikipedia.org/wiki/Topological_sorting

There are several efficient algorithms. One is pretty close to yours, but you only put a vertex in the set when it has no unfinished predecessors. (harold's answer)

Isn't this essentially a level-order traversal kind of problem?

Given that,

An operation can be only performed if all annotated values of the parent vertices (predecessors) are known.

you should start with the vertices that have no parent vertices. (This part has already been figured out by you.)

Next, instead of putting them in a set, put them in a queue so that the first in, first out funda actually allows you to address each vertex in the level-wise order.

If the current vertex's value cannot be computed, put it back in the queue, otherwise put the vertex that are reachable from the current vertex in the queue. Keep computing values for the vertices that have the required parent vertices' value available.

I can almost argue that with some optimizations, this would be the most efficient method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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