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

使用std::unordered_map实现有向图边操作时遇编译错误求助

嘿,我来帮你搞定这个问题!

你想实现O(1)时间的边操作,选std::unordered_map完全是正确的思路——但编译报错十有八九是因为你用作键的类型(大概率是顶点对,比如std::pair<Vertex, Vertex>)没有对应的哈希函数,毕竟unordered_map默认只支持基础类型和部分STL类型的哈希,自定义类型或者std::pair这类组合类型需要你手动提供哈希逻辑。

下面给你几个靠谱的解决方案,按需选择:

方案1:给顶点对自定义哈希函数

如果你的边是用std::pair<FromVertex, ToVertex>作为键(比如顶点是int类型),可以写一个哈希结构体,然后在声明unordered_map的时候指定它:

#include <unordered_map>
#include <utility>

// 针对pair<int, int>的自定义哈希
struct PairHash {
    template <class T1, class T2>
    std::size_t operator () (const std::pair<T1,T2>& p) const {
        // 混合两个哈希值,避免碰撞(也可以用更复杂的算法,比如boost的哈希组合逻辑)
        auto hash1 = std::hash<T1>{}(p.first);
        auto hash2 = std::hash<T2>{}(p.second);
        return hash1 ^ (hash2 << 1);
    }
};

class DirectedGraph {
private:
    // 键:起点-终点对,值:边的成本
    std::unordered_map<std::pair<int, int>, int, PairHash> edgeCosts;
public:
    // O(1) 获取边成本:用find而不是[],避免const容器下的编译错误
    int getEdgeCost(int from, int to) const {
        auto it = edgeCosts.find({from, to});
        return it != edgeCosts.end() ? it->second : -1; // 用-1表示边不存在,可按需调整
    }

    // O(1) 插入/修改边成本:[]操作符完美适配,不存在则插入,存在则覆盖
    void setEdgeCost(int from, int to, int cost) {
        edgeCosts[{from, to}] = cost;
        // C++17及以上也可以用insert_or_assign,语义更清晰:
        // edgeCosts.insert_or_assign({from, to}, cost);
    }
};

方案2:把顶点对转成基础类型作为键

如果不想写自定义哈希,也可以把顶点对转换成uint64_t这类能被默认哈希处理的类型(适合顶点是32位整数的场景):

#include <unordered_map>
#include <cstdint>

class DirectedGraph {
private:
    std::unordered_map<uint64_t, int> edgeCosts;

    // 辅助函数:把两个int顶点转成64位键
    uint64_t getKey(int from, int to) const {
        return (static_cast<uint64_t>(from) << 32) | static_cast<uint32_t>(to);
    }
public:
    int getEdgeCost(int from, int to) const {
        auto it = edgeCosts.find(getKey(from, to));
        return it != edgeCosts.end() ? it->second : -1;
    }

    void setEdgeCost(int from, int to, int cost) {
        edgeCosts[getKey(from, to)] = cost;
    }
};

方案3:自定义顶点类的处理

如果你的顶点是自定义类(比如struct Vertex { int id; }),除了哈希函数,还需要提供相等比较逻辑(要么重载==,要么自定义相等比较器):

#include <unordered_map>
#include <utility>

struct Vertex {
    int id;
    // 重载==,让unordered_map能判断两个顶点是否相等
    bool operator==(const Vertex& other) const {
        return id == other.id;
    }
};

// 针对Vertex的哈希函数
struct VertexHash {
    std::size_t operator()(const Vertex& v) const {
        return std::hash<int>{}(v.id);
    }
};

// 针对pair<Vertex, Vertex>的哈希函数
struct VertexPairHash {
    std::size_t operator()(const std::pair<Vertex, Vertex>& p) const {
        auto hash1 = VertexHash{}(p.first);
        auto hash2 = VertexHash{}(p.second);
        return hash1 ^ (hash2 << 1);
    }
};

class DirectedGraph {
private:
    std::unordered_map<std::pair<Vertex, Vertex>, int, VertexPairHash> edgeCosts;
public:
    // ... 后续的get/set方法和前面类似
};

额外注意的坑

如果你在const成员函数里用[]访问unordered_map会编译失败!因为[]会在键不存在时插入新元素,而const容器不允许修改——所以获取边成本一定要用find方法,这是很多人踩过的坑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:11:58