【转载】深度优先搜索代码

本文章代码中的图用邻接矩阵来表示,所以算法复杂度为O(V^2)。如果用邻接表来表示,那么算法的复杂度为O(V+E)。

DFS可用来判断图中是否有环,展现无向图中的连通分支。
通过DFS,形成一个由多棵深度优先树所组成的深度优先森林。将原先图中的边添加到该森林之后,可以将所有边定义为以下四类:
1.    树边:森林中自带的边(即不在森林生成后,从原先图中添加的边)。
2.    反向边:从某个节点指向祖先的边,包括自己指向自己。非森林自带的边。如果图中存在反向边,则表明存在环。
3.    正向边:从某个节点指向后代的边,非森林自带的边。
4.    交叉边:边的两端点之间没有祖先后代关系,非森林自带的边。



在DFS过程中,可以对任意两点间的边进行分类,对于有向图和无向图,分类情况有所区别。
有向图:
1.    树边:当visit了节点u后,如果边(u, v)存在,且v为WHITE,则该边为树边。
2.    反向边:当visit了节点u后,如果边(u, v)存在,且v为GREY,则该边位反向边。
3.    正向边:当visit了节点u后,如果边(u, v)存在,且v为BLACK,StartTime[u] < StartTime[v] < EndTime[v] < EndTime[u],则边为正向边。
4.    交叉边:当visit了节点u后,如果边(u, v)存在,且v为BLACK,StartTime[v] < EndTime[v] < StartTime[u] < EndTime[u],则边为交叉边。

无向图:
1.    树边:当visit了节点u后,如果边(u, v)存在,且v为WHITE,则该边为树边。
2.    反向边:否则就是反向边。



代码

#include <iostream>
#define MAXLENGTH 1000
#define WHITE 0
#define GREY 1
#define BLACK 2
using namespace std;
//The color of node. They can be used to define the link type between two nodes. WHITE means the node has not been visited. Gray means the node has been searched but its descendants have not been not all visited. Black means that the node and its descendants have all been visited.
int Color[MAXLENGTH];
//the parent of node i
int Parent[MAXLENGTH];
//the first time to be visited
int StartTime[MAXLENGTH];
//the second time to be visited, after visiting the descendants.
int EndTime[MAXLENGTH];
//the node graph
bool Graph[MAXLENGTH][MAXLENGTH];
//count the time
int time_count;
void DFS_Visit(int, int, int);
/**
 * @brief Dfs graph who has n nodes
 *
 * @param n: the nodes‘ number
 */
void DFS(int n)
{
    //initialization
    for (int i = 0; i < n; ++i)
    {
        Color[i] = WHITE;
    }
    time_count = 0;
    //start DFS visit. Some nodes may can‘t be visited if starts from some nodes, so loop to ensure that every node can be visited.
    for (int i = 0; i < n; ++i)
    {
        if (Color[i] == WHITE)
        {
            DFS_Visit(i, -1, n);
        }
    }
}
/**
 * @brief DFS visit node
 *
 * @param node: the node to be visited
 * @param parent: the parent of the node
 * @param n: the nodes number in the graph
 */
void DFS_Visit(int node, int parent, int n)
{
    Color[node] = GREY;
    Parent[node] = parent;
    StartTime[node] = time_count++;
    for (int i = 0; i < n; ++i)
    {
        if (Graph[node][i] && Color[i] == WHITE)
        {
            DFS_Visit(i, node, n);
        }
    }
    Color[node] = BLACK;
    EndTime[node] = time_count++;
}
/**
 * @brief Print the path from start to end
 *
 * @param end: the end node
 */
void PrintPath(int end)
{
    cout << "Show path from end to start" << endl;
    while (end != -1)
    {
        cout << end << " start-time:" << StartTime[end] << "   end-time:" << EndTime[end] << endl;
        end = Parent[end];
    }
}
int main()
{
    int n;
    while (cin >> n, n != 0)
    {
        for (int i = 0; i < n; ++i)
        {
            for (int j = 0; j < n; ++j)
            {
                cin >> Graph[i][j];
            }
        }
        int end;
        DFS(n);
        while (cout << "Input the end node, -1 means no more search." << endl, cin >> end, end != -1)
        {
            PrintPath(end);
        }
    }
}
时间: 2024-11-04 12:33:17

【转载】深度优先搜索代码的相关文章

“生动”讲解——深度优先搜索与广度优先搜索

深度优先搜索(Depth First Search,DFS) 主要思想:不撞南墙不回头 深度优先遍历的主要思想就是:首先以一个未被访问过的顶点作为起始顶点,沿当前顶点的边走到未访问过的顶点:当没有未访问过的顶点时,则回到上一个顶点,继续试探访问别的顶点,直到所有的顶点都被访问. 沿着某条路径遍历直到末端,然后回溯,再沿着另一条进行同样的遍历,直到所有的顶点都被访问过为止. 图解: 分析: 通过上面的图例可以非常直观的了解深度优先搜索的工作方式.下面来分析一下如何用代码来实现它. 大家都知道,深度

无向图的深度优先与广度优先搜索代码实现

图采用了邻接表的形式储存. 带不带权都无所谓的 深度优先搜索 Depth First Search 道理和树的先序遍历差不多,把将要访问的点入栈,然后从栈里取点进行访问. 由于这只是类中的一个成员函数,有些被调用的函数的具体代码将会在文章最后补上 ,但是函数功能看注释就好了 1 //深度优先 2 void GraphAdjacencyListWeight::DFSAdvanced(int StartVertex) { 3 int *visited = new int[VertexNumber];

算法导论22.3深度优先搜索 练习总结 (转载)

22.3-1 画一个 3*3 的网格,行和列的抬头分别标记为白色.灰色和黑色,对于每个表单元 (i, j),请指出对有向图进行深度优先搜索的过程中,是否可能存在一条边,链接一个颜色为 i 的结点和一个颜色为 j 的结点.对于每种可能的边,指明该种边的类型.另外,请针对无向图的深度优先搜索再制作一张这样的网格. ANSWER:   22.3-2 给出深度优先搜索算法在图 22-6 上的运行过程.假定深度优先搜索算法的第 5~7 行的 for 循环是以字母表顺序依次处理每个结点,假定每条邻接链表皆以

代码与算法集锦-归并排序+树状数组+快排+深度优先搜索+01背包(动态规划)

归并排序 求逆序数 归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 首先考虑下如何将将二个有序数列合并.这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数.然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可. //将有序数组a[]和b[]合并到c[]中 void MemeryArray(int a[], int n, int b[], int m, int c

迷宫寻址中深度优先搜索的递归和非递归算法比较

巧若拙(欢迎转载,但请注明出处:http://blog.csdn.net/qiaoruozhuo) 本文只探究迷宫寻址中深度优先搜索的递归和非递归算法比较,其他相关代码详见<迷宫问题(巧若拙)>http://blog.csdn.net/qiaoruozhuo/article/details/41020745 深度优先搜索的递归算法是很容易实现的,只需设置一个驱动函数,然后递归调用子函数就可以了. 代码如下: int DeepSearchWay()//寻找路径:深度搜索 { CopyMiGong

unity 使用深度优先搜索生成迷宫之二

之前写过一篇使用深度优先搜索生成随机迷宫的文章 https://www.cnblogs.com/JinT-Hwang/p/9599913.html 今天做了一下优化,使用unity的TileMap来做,并且代码减少到100行以内. 先看一下效果图 下面直接是代码,至于在unity中怎么创建tilemap资源这里就不讲了: using System.Collections; using System.Collections.Generic; using UnityEngine; using Uni

深度优先搜索与广度优先搜索算法理解

深度优先搜索算法和广度优先搜索算法是图论中两个有意思也很实用的算法,下面我们来看看这两个算法. 严书中,给出的利用深度优先搜索(Deep First Search)算法进行图的遍历伪码如下 1 Boolean visited[MAX]; //标志数组 2 Status (*VisitFunction)(int v); //访问函数 3 4 void DFSTraverse(Graph G, Status (*Visit)(int v)) 5 { 6 VisitFunction = Visit;

[ACM] 1016 Prime Ring Problem (深度优先搜索)

Prime Ring Problem Problem Description A ring is compose of n circles as shown in diagram. Put natural number 1, 2, ..., n into each circle separately, and the sum of numbers in two adjacent circles should be a prime. Note: the number of first circle

POJ 1979 Red and Black 深度优先搜索上手题

Red and Black Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 21738   Accepted: 11656 Description There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A man is standing on a black tile. From a