首页 > 编程语言 >C++搜索问题

C++搜索问题

时间:2025-01-15 15:59:28浏览次数:3  
标签:int graph C++ 问题 start vector 搜索 include

C++ 中的搜索算法是指在数据结构或图中寻找某些特定元素或满足条件的路径的算法。搜索算法广泛应用于问题求解、路径规划、数据检索等领域。常见的搜索算法可以分为两大类:

  1. 无权搜索算法:如深度优先搜索(DFS)、广度优先搜索(BFS)。
  2. 启发式搜索算法:如A算法、双向搜索、IDA算法等。

1. 深度优先搜索(DFS)

特点

  • DFS 是一种递归或栈实现的搜索策略,从起点出发尽可能深入,然后再回溯继续探索未访问的路径。
  • 时间复杂度:O(V+E)O(V + E)O(V+E)(V是节点数,E是边数)。
  • 适用场景:路径搜索、连通性检测、拓扑排序等。

实现方式

递归版 DFS
#include <iostream>
#include <vector>
using namespace std;

void dfs(int node, vector<vector<int>>& graph, vector<bool>& visited) {
    visited[node] = true;
    cout << "访问节点: " << node << endl;

    for (int neighbor : graph[node]) {
        if (!visited[neighbor]) {
            dfs(neighbor, graph, visited);
        }
    }
}

int main() {
    int n = 5; // 节点数
    vector<vector<int>> graph(n);

    // 构建无向图
    graph[0] = {1, 2};
    graph[1] = {0, 3};
    graph[2] = {0, 4};
    graph[3] = {1};
    graph[4] = {2};

    vector<bool> visited(n, false);
    dfs(0, graph, visited); // 从节点 0 开始搜索
    return 0;
}
非递归版 DFS

使用显式栈来模拟递归调用栈。

#include <iostream>
#include <vector>
#include <stack>
using namespace std;

void dfs_iterative(int start, vector<vector<int>>& graph, vector<bool>& visited) {
    stack<int> s;
    s.push(start);

    while (!s.empty()) {
        int node = s.top();
        s.pop();

        if (!visited[node]) {
            visited[node] = true;
            cout << "访问节点: " << node << endl;

            for (int neighbor : graph[node]) {
                if (!visited[neighbor]) {
                    s.push(neighbor);
                }
            }
        }
    }
}

int main() {
    int n = 5;
    vector<vector<int>> graph(n);
    graph[0] = {1, 2};
    graph[1] = {0, 3};
    graph[2] = {0, 4};
    graph[3] = {1};
    graph[4] = {2};

    vector<bool> visited(n, false);
    dfs_iterative(0, graph, visited);
    return 0;
}

2. 广度优先搜索(BFS)

特点

  • BFS 是一种层次搜索策略,先访问所有距离起点最近的节点,然后逐层向外扩展。
  • 时间复杂度:O(V+E)O(V + E)O(V+E)。
  • 适用场景:最短路径(无权图)、连通性检测等。

实现方式

使用队列实现 BFS。

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

void bfs(int start, vector<vector<int>>& graph) {
    int n = graph.size();
    vector<bool> visited(n, false);
    queue<int> q;

    q.push(start);
    visited[start] = true;

    while (!q.empty()) {
        int node = q.front();
        q.pop();

        cout << "访问节点: " << node << endl;

        for (int neighbor : graph[node]) {
            if (!visited[neighbor]) {
                visited[neighbor] = true;
                q.push(neighbor);
            }
        }
    }
}

int main() {
    int n = 5;
    vector<vector<int>> graph(n);
    graph[0] = {1, 2};
    graph[1] = {0, 3};
    graph[2] = {0, 4};
    graph[3] = {1};
    graph[4] = {2};

    bfs(0, graph);
    return 0;
}

3. A*搜索算法

特点

  • A* 是一种启发式搜索算法,结合了广度优先搜索和Dijkstra算法的优点。
  • f(n) = g(n) + h(n)
    • g(n)g(n)g(n):起点到当前节点的实际代价。
    • h(n)h(n)h(n):当前节点到目标节点的估算代价(启发式函数)。
  • 时间复杂度:根据启发式函数的设计,通常优于普通BFS和Dijkstra。

实现方式

#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;

struct Node {
    int x, y, cost, heuristic;
    bool operator>(const Node& other) const {
        return (cost + heuristic) > (other.cost + other.heuristic);
    }
};

int heuristic(int x1, int y1, int x2, int y2) {
    return abs(x1 - x2) + abs(y1 - y2); // 曼哈顿距离
}

void a_star(vector<vector<int>>& grid, pair<int, int> start, pair<int, int> goal) {
    int rows = grid.size();
    int cols = grid[0].size();
    vector<vector<int>> cost(rows, vector<int>(cols, INT_MAX));
    priority_queue<Node, vector<Node>, greater<Node>> pq;

    int dx[] = {0, 1, 0, -1};
    int dy[] = {1, 0, -1, 0};

    pq.push({start.first, start.second, 0, heuristic(start.first, start.second, goal.first, goal.second)});
    cost[start.first][start.second] = 0;

    while (!pq.empty()) {
        Node current = pq.top();
        pq.pop();

        if (current.x == goal.first && current.y == goal.second) {
            cout << "到达目标点,总代价为: " << current.cost << endl;
            return;
        }

        for (int i = 0; i < 4; ++i) {
            int nx = current.x + dx[i];
            int ny = current.y + dy[i];

            if (nx >= 0 && nx < rows && ny >= 0 && ny < cols && grid[nx][ny] == 0) {
                int new_cost = current.cost + 1;
                if (new_cost < cost[nx][ny]) {
                    cost[nx][ny] = new_cost;
                    pq.push({nx, ny, new_cost, heuristic(nx, ny, goal.first, goal.second)});
                }
            }
        }
    }

    cout << "无法到达目标点" << endl;
}

int main() {
    vector<vector<int>> grid = {
        {0, 0, 0, 0},
        {0, 1, 1, 0},
        {0, 0, 0, 0},
        {0, 1, 0, 0}
    };
    pair<int, int> start = {0, 0};
    pair<int, int> goal = {3, 3};

    a_star(grid, start, goal);
    return 0;
}

4. 双向搜索

特点 

  • 双向搜索同时从起点和目标节点进行搜索,缩小搜索范围,适用于无向图。

总结

  1. 无权图搜索:DFS(深度优先搜索)、BFS(广度优先搜索)。
  2. 权重图搜索:A*算法、Dijkstra算法、Bellman-Ford算法。
  3. 全局搜索:Floyd-Warshall、Johnson算法。

C++ 强大的 STL(如 vectorpriority_queue)可以有效实现这些算法,使得代码简洁高效。在实际应用中,选择合适的搜索算法和优化技巧是关键。

 

标签:int,graph,C++,问题,start,vector,搜索,include
From: https://blog.csdn.net/Annconda/article/details/145135851

相关文章

  • 2025-1-15-十大经典排序算法 C++与python
    文章目录十大经典排序算法比较排序1.冒泡排序2.选择排序3.插入排序4.希尔排序5.归并排序6.快速排序7.堆排序非比较排序8.计数排序9.桶排序10.基数排序十大经典排序算法十大经典排序算法可以分为比较排序和非比较排序:前者包括冒泡排序、选择排序、插......
  • 解决1235 - This version of MySQL doesn‘t yet support ‘LIMIT & IN/ALL/ANY/SOME
    文章讲述了在MySQL中尝试使用IN关键字结合LIMIT子句时遇到的1235错误,即不支持LIMIT&IN/ALL/ANY/SOMEsubquery。解决方案是将子查询封装到另一个查询中,避免IN和LIMIT在同一层次。通过创建一个新的子查询来获取TOP3用户ID,然后在外层查询中使用这些ID过滤用户。SELECT *FROM `u......
  • 高效团队如何选择问题管理工具?六款推荐与理由
    1.板栗看板(BanliKanban)推荐理由:板栗看板是由重庆赛迪信息公司研发的在线协同文档编辑与项目管理工具,专为中国企业的团队协作需求量身打造。核心功能:板栗看板集任务管理、实时协作编辑、进度追踪于一体,通过简洁直观的界面帮助团队掌握开发节奏。适用场景:适合中大型企业,特......
  • Linux 文件乱码问题及基于 inode 的排查与解决
    Linux文件乱码问题及基于inode的排查与解决在Linux系统中,文件乱码通常是由于显示或读取时使用的字符编码与文件实际编码不一致导致的。本文将详细介绍Linux文件乱码的常见原因、解决方法,包括压缩包解压后的乱码问题,并结合inode的概念,讲解如何利用inode进行问题排查和......
  • 代码审计-PHP原生开发&SQL注入&数据库监控&正则搜索&文件定位&静态分析
    知识点1、PHP审计-原生态开发-SQL注入&数据库语句监控2、PHP审计-原生态开发-SQL注入&正则匹配搜索3、PHP审计-原生态开发-SQL注入&功能追踪代码审计分类:1、原生态开发-代码审计源码案例2、框架类开发-代码审计源码案例3、组件类开发-代码审计源码案例4、前端类开发-代码......
  • 如何处理网站内容被删除并恢复数据库文件的问题
    用户反馈其网站内容被删除,希望恢复特定日期(如4月13日)的数据库备份文件。这可能是由于恶意攻击、误操作或其他未知原因引起的。解决方案确认备份情况登录到托管服务提供商的管理面板,查看是否有可用的备份文件。特别关注指定日期(如4月13日)的备份。如果发现备份文件缺失或损坏......
  • 如何解决服务器环境下强制删除文件或文件夹提示找不到该项目的问题?
    在服务器环境中,有时会遇到无法通过常规方法(如改名或使用 del 命令)删除文件或文件夹的情况。系统可能会提示“找不到该项目”,或者删除操作没有任何提示和响应。这通常是由于文件或文件夹被占用、权限问题、路径过长或其他系统级限制所引起的。为了解决这个问题,可以创建一个批处......
  • 如何解决定义了重复的 "system.web.extensions/scripting/scriptResourceHandler" 节
    问题描述在使用ASP.NET应用程序时,可能会遇到配置文件中定义了重复的 "system.web.extensions/scripting/scriptResourceHandler" 节的问题。这通常会导致应用程序无法正常启动或运行,并抛出配置错误。此问题的具体表现形式是:当尝试访问网站时,会收到一个配置错误提示,指出存在重复......
  • c++&& SDK打包过程
     在C++中,SDK(SoftwareDevelopmentKit)打包工具的选择和使用通常取决于您的具体需求和目标平台。以下是一个详细的步骤描述,用于创建和打包一个C++SDK。这里我们假设您已经有一个C++项目需要打包为SDK。步骤一:准备你的C++项目项目结构规划:确定你的SDK包含哪些功能,比如源代......
  • Effective C++ 之【条款7:为多态基类声明virtual析构函数】
    文章目录Tips1Tips2一、为什么要有virtual析构函数?二、为什么有时候不要声明虚构函数?三、使用一下纯虚函数。TodayThinking~Tips1polymorphic(带有多态性质的)baseclasses应该声明一个virtual的虚构函数。如果class带有任何virtual函数,它就应该拥有一个virtual析构......