unordered_map自定义数据结构

本文介绍了如何在C++中使用自定义数据结构(如SHA1FP_s)作为unordered_set或unordered_map的键。当使用自定义数据结构时,需要提供哈希函数和相等比较函数。示例中提供了自定义的哈希器(Hasher)和比较器(Equaler)。此外,还展示了如何使用vector作为键,并提供了相应的哈希和比较方法。通过这些方法,可以有效地处理自定义数据结构在哈希容器中的存储和查找操作。
摘要由CSDN通过智能技术生成

unordered_map自定义数据结构

1. 说明

一般来说,我们经常使用的STL 哈希的使用方法如下👇

unordered_set<int> uset;
unordered_map<int, unordered_set<int>> my_ump; // 拉链法

但是当我们更换数据结构(将key对应的int,更换为自定义数据结构时)时,会报错👇

2. 自定义数据结构(或者类,或者容器等)使用方法

2.1 自定义数据结构报错

这里使用的是举例说明,假设我们有如下数据结构:(其实是一个160bit的“指纹”(哈希值))

typedef struct SHA1FP {
  uint64_t fp1;
  uint32_t fp2, fp3, fp4;
} SHA1FP_s;

如果和之前一样,使用如下定义👇

unordered_set<SHA1FP_s> uset; //将会报错

将会报错如下👇(即找不到对应的数据结构——哈希方法、对比是否最终相等的方法等)

std::unordered_set<SHA1FP_s> uset
the default constructor of "std::unordered_set<SHA1FP_s, std::hash<SHA1FP_s>, std::equal_to<SHA1FP_s>, std::allocator<SHA1FP_s>>" cannot be referenced -- it is a deleted functionC/C++(1790)

2.2 使用自定义数据结构的方法

根据之前的报错信息,自定义哈希方法、对比是否相同的方法。

2.2.0 可以运行的uset定义方法
unordered_set<SHA1FP_s, Hasher, Euqaler> uset;

后面将分别解释Hasher (自定义哈希方法) 和Equaler(自定义数据结构是否相同)的含义。

2.2.1 自定义哈希方法
struct Hasher{
    size_t operator()(SHA1FP_s& a) const {
        return a.fp1;
    }
};
2.2.2 对比是否相同

因为hash是可能会碰撞的(可能存在两个不同的sha1,分别是a和b,a.fp1 == b.fp1 但是a != b)——需要判断所有值是否相同

struct Euqaler{
    bool operator()(SHA1FP_s& a, SHA1FP_s& b) const {
        return ((a.fp1 == b.fp1) && (a.fp2 == b.fp2) && (a.fp3 == b.fp3) && (a.fp3 == b.fp3));
    }
};

3. 完整代码

3.1 运行方法

将下面代码复制到hash_customize.cpp,然后使用如下命令即可编译成功👇

g++ hash_customize.cpp -o hash_customize

3.2 完整代码

// g++ hash_customize.cpp -o hash_customize
#include <iostream>
#include <unordered_set>
#include <vector>
using namespace std;

typedef struct SHA1FP {
  uint64_t fp1;
  uint32_t fp2, fp3, fp4;
} SHA1FP_s;

struct Hasher{
    size_t operator()(SHA1FP_s& a) const {
        return a.fp1;
    }
};

struct Euqaler{
    bool operator()(SHA1FP_s& a, SHA1FP_s& b) const {
        return ((a.fp1 == b.fp1) && (a.fp2 == b.fp2) && (a.fp3 == b.fp3) && (a.fp3 == b.fp3));
    }
};

int main() {
    // test_customize_umap();
    unordered_set<SHA1FP_s, Hasher, Euqaler> uset;
    exit(0);
}

4. 例子2:vector当key

4.1 运行方法

将下面代码复制到hash_customize.cpp,然后使用如下命令即可编译成功👇

g++ hash_customize.cpp -o hash_customize

使用如下命令运行👇

./hash_customize

4.2 完整代码(请注意看注释部分)

// g++ hash_customize.cpp -o hash_customize
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;

void print_vec(const vector<int>& vec) {
    for (auto elem : vec) {
        cout << elem << " ";
    }
    cout << endl;
}

// 这里直接使用vec中的第一个元素作为hash value(这样做并不好,碰撞率会比较高,但是十分直观),另一种更加高效的方式在my_Hasher中
struct Hasher{
    size_t operator()(const vector<int>& a) const {
        return a[0];
    }
};

// 更加高效的自定义hash方法(用来代替Hasher)
struct my_Hasher{
    size_t operator ()(const vector<int>& a) const {
        hash<int> hsh;
        int seed = 0;

        for (auto elem : a) {
            seed ^= hsh(elem) + 0x803923 + (seed << 5) + (seed >> 3); //这里左移多少位,右移多少位,还有加0x803923都是随便写的,也不一定非是这样写(不一定非要左移或者右移,总之就是一个函数,尽量避免碰撞)
        }
        return seed;
    }
};

struct Equaler{
    bool operator()(const vector<int>& a, const vector<int>& b) const {
        return a == b;
    }
};

void test_customize_umap() {
    unordered_map<vector<int>, vector<int>, Hasher, Equaler> ump;
    vector<int> helo = {1,2,3};

    ump[helo] = helo;
    for (auto elem : ump) {
        print_vec(elem.first); 
        print_vec(elem.second);
    }
}


int main() {
    test_customize_umap();
    // unordered_set<SHA1FP_s, Hasher, Euqaler> uset;
    exit(0);
}

4.3 运行结果

levi@LEVI1:~/code$ ./hash_customize 
1 2 3 
1 2 3 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值