数据结构+算法(搜索类:BFS + DFS )

BFS

典型搜索树示意图

// 计算从起点 start 到终点 target 的最近距离
int BFS(Node start, Node target) {
    std::queue<Node> q; // 核心数据结构
    std::set<Node> visited; // 避免走回头路
    
    q.push(start); // 将起点加入队列
    visited.insert(start);
    int step = 0; // 记录扩散的步数

    while (!q.empty()) {
        int sz = q.size();
        /* 将当前队列中的所有节点向四周扩散 */
        for (int i = 0; i < sz; i++) {
            auto cur = q.front();
          	q.pop();
            /* 划重点:这里判断是否到达终点 */
            if (cur is target)
                return step;
            /* 将 cur 的相邻节点加入队列 */
            for (Node x : cur.adj()) {
                if (visited.count(x) < 0) {
                    q.push(x);
                    visited.insert(x);
                }
            }
        }
        /* 划重点:更新步数在这里 */
        step++;
    }
}

 

DFS

决策树

 

/*
*@param: origin_source 一般是给定的输入
*@param: track_res 期望的最终结果
*@param: single_track 期望目标结果中的单个case
*@param: cur_index 当前执行的阶段
*/
void backtrack(DataType origin_source, vector<DataType> track_res, DataType& single_track,int cur_index) {
    // 触发结束条件。这里用cur_index 或者single_track 的内容做判断均可
    if (cur_index == 边界条件) { 
        track_res.push_back(single_track);
        return;
    }
    
    for (int i = 0; i < origin_source.size(); i++) {
        // 排除不合法的选择
        if (isValid())
            continue;
        // 做选择,将当前选择加入
        single_track.push(origin_source[i]);
        // 进入下一层决策树
        backtrack(origin_source, track_res, singhle_track, cur_index++);
        // 取消选择
        single_track.pop();
    }
}

岛屿类题目

void dfs(vector<vector<int>>& grid, int i, int j, vector<vector<bool>>& visited) {
    int m = grid.size(), n = grid[0].size();
    if (i < 0 || j < 0 || i >= m || j >= n) {
        return;
    }
    if (visited[i][j]) {
        return;
    }
    visited[i][j] = true;
    dfs(grid, i - 1, j, visited); // 上
    dfs(grid, i + 1, j, visited); // 下
    dfs(grid, i, j - 1, visited); // 左
    dfs(grid, i, j + 1, visited); // 右
}

上述是一般类型的模板。但是通常情况下,面对岛屿问题会选择使用“岛屿淹没法”,也就是直接将 gird[i][j] == 0 (假设0是海水),这样可以不用维护 visited 数组,同样达到了不走回头路的目的

    // 从 (i, j) 开始,将与之相邻的陆地都变成海水
    void dfs(vector<vector<char>>& grid, int i, int j) {
        int m = grid.size(), n = grid[0].size();
        if (i < 0 || j < 0 || i >= m || j >= n) {
            // 超出索引边界
            return;
        }
        if (grid[i][j] == '0') {
            // 已经是海水了
            return;
        }
        // 将 (i, j) 变成海水
        grid[i][j] = '0';
        // 淹没上下左右的陆地
        dfs(grid, i + 1, j);
        dfs(grid, i, j + 1);
        dfs(grid, i - 1, j);
        dfs(grid, i, j - 1);
    }

 

posted @ 2021-12-21 01:38  Clovran-Wong  阅读(32)  评论(0编辑  收藏  举报