You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中如何跟踪遍历过程中的已访问点?

更适合跟踪访问点的C++解决方案

嘿,作为曾经也踩过容器选择坑的C++初学者,我太懂你这种困惑了!用std::map来跟踪访问点确实有点“杀鸡用牛刀”,下面给你几个更贴合需求的高效方案,一步步来:

1. 优先选std::unordered_map(哈希表,平均O(1)效率)

std::unordered_map是哈希表实现,插入和查找的平均时间复杂度是O(1),比std::map的O(logn)快不少,而且不需要写比较器,只需要给你的点类型提供一个哈希函数(如果是自定义类型的话)。

举个最常见的二维整数坐标例子:

#include <unordered_map>
#include <utility>

// 给std::pair<int,int>写个简单的哈希函数
struct PairHash {
    template <class T1, class T2>
    std::size_t operator () (const std::pair<T1,T2>& p) const {
        // 组合两个整数的哈希值,避免简单异或的冲突
        auto hash1 = std::hash<T1>{}(p.first);
        auto hash2 = std::hash<T2>{}(p.second);
        return hash1 ^ (hash2 << 1);
    }
};

// 初始化访问标记容器
std::unordered_map<std::pair<int, int>, bool, PairHash> visited;

// 标记点(x,y)已访问
visited[{x, y}] = true;

// 检查是否访问过
if (visited.find({x, y}) != visited.end()) {
    // 这里写已访问后的逻辑
}

如果是你自己定义的Point结构体,只需要额外重载==运算符(哈希表需要判断键是否相等):

struct Point {
    int x;
    int y;
    // 必须重载==,用于哈希表判断键是否重复
    bool operator==(const Point& other) const {
        return x == other.x && y == other.y;
    }
};

// 给Point写哈希函数
struct PointHash {
    std::size_t operator()(const Point& p) const {
        return std::hash<int>{}(p.x) ^ (std::hash<int>{}(p.y) << 1);
    }
};

// 使用方式和上面一样
std::unordered_map<Point, bool, PointHash> visited;

2. 不想写哈希函数?用std::set更轻量

如果你觉得写哈希函数麻烦,std::set是个不错的替代——它只需要你的点类型支持比较(比如重载<运算符),而且它专门用来存储唯一元素,刚好符合“跟踪是否访问过”的需求(因为同一个点只会存一次)。

对于std::pair<int,int>,标准库已经默认支持<比较了,直接用就行:

#include <set>
#include <utility>

std::set<std::pair<int, int>> visited;

// 标记访问
visited.insert({x, y});

// 检查是否访问过(count返回1就是存在,0就是不存在)
if (visited.count({x, y})) {
    // 已访问逻辑
}

如果是自定义结构体,只需要重载<运算符:

struct Point {
    int x;
    int y;
    // 重载<,先比x,x相同再比y
    bool operator<(const Point& other) const {
        if (x != other.x) return x < other.x;
        return y < other.y;
    }
};

std::set<Point> visited;

不过要注意,std::set底层是红黑树,插入查找是O(logn),比std::unordered_map慢一点,但比std::map更贴合你的场景——毕竟你只需要存点,不需要键值对,std::map会额外存储一个值,纯属浪费。

3. 坐标范围固定?直接用数组/二维数组(效率天花板)

如果你的题是网格遍历、迷宫搜索这种场景,点的坐标范围是固定且不大的(比如x从0到1000,y从0到1000),那直接用二维布尔数组绝对是最优解!没有任何容器的额外开销,访问速度是O(1),代码还超级简单。

示例代码:

// 假设坐标范围是0<=x<1000,0<=y<1000,初始化全为false
bool visited[1000][1000] = {false};

// 标记点已访问
visited[x][y] = true;

// 检查是否访问过
if (visited[x][y]) {
    // 已访问逻辑
}

如果坐标范围需要动态设置,用std::vector也很方便:

int max_x = 1000;
int max_y = 1000;
// 初始化一个max_x行max_y列的二维vector,默认值都是false
std::vector<std::vector<bool>> visited(max_x, std::vector<bool>(max_y, false));

为什么说std::map是大材小用?

std::map底层是红黑树,核心优势是有序存储和范围查找,但你这个场景只是要判断“某个点是否存在”,完全不需要有序的特性。而且std::map是键值对容器,你其实只需要存键(点),不需要对应的值,用它会浪费空间和性能——上面的几种方案都更贴合你的需求,代码也更简单。

内容的提问来源于stack exchange,提问作者Blubber

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:17:39