深搜和广搜是最重要的几种算法之一,理解深搜和广搜的关键在于理解 递归状态机容器适配器--堆&&栈集合分类 四个概念。

在搜索中,节点的状态有很多种(节点的状态此时主要根据操作来定义),比如:未被访问的节点,被访问但是后续仍要用于寻找相邻节点的点,被访问并且后续不会被用到的点。其中,第二类点仍有使用的必要,因此将之放入特定容器,也就是队列或者栈。

深度优先搜索

深度优先搜索是一种用于遍历或搜索图或者树的算法。沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。属于盲目搜索。

// 深度优先搜索
vector<int> G[MAX];
bool visit[MAX];
stack<int> stack;

void DFS(int u){
    visit[u] = 1;
    for(int i = 0;i < G[u].size();i++){ // 邻接关系
        int v = G[u][i];
        if(!visit[v]){
            DFS(v);
        }
    }
}

void Dfs(int u){
    visit[u] = 1;
    stack.push(u);
    while(!stack.empty()){
        int u = stack.top();
        stack.pop();
        for(int i = 0;i < G[u].size();i++){ // 邻接关系
            int v = G[u][i];
            if(!visit[v]){
                visit[v] = 1;
                stack.push(v);
            }
        }
    }
    
}

深度搜索的逻辑是这样的:将被访问但是后续仍要用于寻找相邻节点的点存入栈容器,这样的话,最先被访问的节点将是最后用于寻找相邻节点的点。也就实现了所谓的回溯。

| A B C D E F G H I

——————-> 访问顺序

| A B C D E F G H I

<——————- 寻找邻接点的顺序

广度优先搜索

广度优先搜索算法(英语:Breadth-First-Search,缩写为BFS),又译作宽度优先搜索,或横向优先搜索,是一种图形搜索算法。简单的说,BFS是从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。广度优先搜索的实现一般采用open-closed表。属于盲目搜索。

// 深度优先搜索
vector<int> G[MAX];
bool visit[MAX];
stack<int> stack;

void DFS(int u){
    visit[u] = 1;
    for(int i = 0;i < G[u].size();i++){ // 邻接关系
        int v = G[u][i];
        if(!visit[v]){
            DFS(v);
        }
    }
}

void Dfs(int u){
    visit[u] = 1;
    stack.push(u);
    while(!stack.empty()){
        int u = stack.top();
        stack.pop();
        for(int i = 0;i < G[u].size();i++){ // 邻接关系
            int v = G[u][i];
            if(!visit[v]){
                visit[v] = 1;
                stack.push(v);
            }
        }
    }
}

广度搜索的逻辑是这样的:将被访问但是后续仍要用于寻找相邻节点的点存入队列容器,这样的话,最先被访问的节点将是最先用于寻找相邻节点的点。

A B C D E F G H I

——————-> 访问顺序

A B C D E F G H I

——————–> 寻找邻接点的顺序