图的遍历

对于图的操作,最基本的就是对图的遍历了,图的遍历主要有两种思想,一种是DFS(Deepth First Search)深度优先遍历,另外一种是BFS(Breadth First Search)广度优先遍历
  • DFS
    • 算法特点:DFS算法,从名字中就可以得出信息,深度优先的,那么在算法的执行过程中,总是将沿着一条路径一直深入,直到没有路径了再返回查看其他路径。可以看出,DFS算法是一种递归的过程,我们再联想到树的遍历中,其实DFS算法就是树的先序遍历。
    • 算法具体代码
      • 递归版
        • 具体代码:
int graph[N][N] = {
        { 0, 1, 1, 0, 0 },
        { 0, 0, 1, 0, 1 },
        { 0, 0, 1, 0, 0 },
        { 1, 1, 0, 0, 1 },
        { 0, 0, 1, 0, 0 }
};
int visited[N] = { 0, };
void DFS(int start)
{
        visited[start] = 1;
        for (int i = 0; i < N; i++)
        {
            if (!visited[i] && graph[start][i] == 1) // 找到相邻的点,同时这个点没有被访问过
                DFS(i);
       }
        cout << start << " ";
    }
int main()
{
        for (int i = 0; i < N; i++)
        {
            if (!visited[i])
                DFS(i);
        }
        return 0;
    }
  * 算法分析:由于是递归调用,那么每次递归都是一个单元,这个单元需要做的事情就是去找相邻的没有访问过的节点,对这个节点重复递归,而去寻找这样的节点就是递归的终止条件,即是如果没有找到这样的点,那么递归终止,返回上一层调用
* **非递归版**
  * 具体代码:
int graph[N][N] = {
    { 0, 1, 1, 0, 0 },
    { 0, 0, 1, 0, 1 },
    { 0, 0, 1, 0, 0 },
    { 1, 1, 0, 0, 1 },
    { 0, 0, 1, 0, 0 }
};
int visited[N] = { 0, };
void DFS(int start)
{
          stack s; // 使用一个栈进行辅助
          s.push(start);
          visited[start] = 1;
          bool isPush = false;
          while (!s.empty())
          {
              isPush = false;
              int v = s.top();
              for (int i = 0; i < N; i++)
              {
                if (graph[v][i] == 1 && !visited[i])
                {
                    visited[i] = 1;
                    s.push(i);
                    isPush = true;
                    break; // 找到了一个符合节点就先弹出当前位置
                }
              }
              if (!isPush)
              {
                  cout << v << " ";
                  s.pop();
              }
           }
}
int main()
{
          for (int i = 1; i <= N; i++)
          {
              if (!visited[i])
                  DFS(i);
          }
          return 0;
}
  * 算法分析:非递归的情况下,使用迭代的思想,需要借助一个栈去模拟递归的过程,然后用while循环进行控制,在非递归的情况下需要去手动加上两个东西:
    * 终止条件:利用一个标记来作控制,用来控制找不到点的情况
    * 栈行为:如果找到一个符合的点,那么就将其压入栈,并且弹出本次循环,如果遇到终止条件,那么就将目前的栈弹出一个
  • BFS
    • 算法特点:BFS从字面上来理解就是广度搜索,与深度搜索不同的是,BFS会将每个节点的周围符合条件的节点都遍历之后才会继续向下遍历,BFS实际上和树的层序遍历很像。
    • 算法实际代码
int maze[N][N] = {
      { 0, 1, 1, 0, 0 },
      { 0, 0, 1, 1, 0 },
      { 0, 1, 1, 1, 0 },
      { 1, 0, 0, 0, 0 },
      { 0, 0, 1, 1, 0 }
};
int visited[N + 1] = { 0, };
void BFS(int start)
{
      queue Q;
      Q.push(start);
      visited[start] = 1;
      while (!Q.empty())
      {
          int front = Q.front();
          cout << front << " ";
          Q.pop();
          for (int i = 1; i <= N; i++)
          {
              if (!visited[i] && maze[front - 1][i - 1] == 1)
              {
                  visited[i] = 1;
                  Q.push(i);
              }
          }
      }
  }
int main()
{
    for (int i = 1; i <= N; i++)
    {
        if (visited[i] == 1)
            continue;
        BFS(i);
    }
    return 0;
}
  • 算法分析
    BFS实际上市借助了队列这种结构,对于每个节点,都将它相邻的同时符合条件的节点压入到队列中,然后在遍历完这个节点的时候就将这个节点给压出队列

你可能感兴趣的:(图的遍历)