std::unordered_map中使用std::vector<int>,std::vector<std::string> , std::vector<double> 作为键

     std::unordered_map中使用std::vector<int>作为键

在这个例子中,使用了 std::unordered_map<std::vector<int>, std::tuple<std::vector<double>, std::vector<double>, std::vector<int>>> 来存储每个组合的边长和夹角信息。这个时候,自定义哈希函数就会被用来计算 std::vector<int> 的哈希值,从而支持快速的插入和查找操作。 

std::unordered_map<std::vector<int>, std::tuple<std::vector<double>, std::vector<double>, std::vector<int>>> edgeMap;

// 当插入元素时:
std::vector<int> combo = {1, 2, 3, 4};
std::vector<double> edges = {1.0, 2.0, 3.0, 4.0};
std::vector<double> angles = {0.5, 0.5, 0.5, 0.5};
edgeMap[combo] = std::make_tuple(edges, angles, combo);

// 当查找元素时:
if (edgeMap.find(combo) != edgeMap.end()) {
    auto [storedEdges, storedAngles, storedCombo] = edgeMap[combo];
    // 使用 storedEdges, storedAngles, storedCombo
}

std::unordered_map<std::vector<int>, std::pair<std::vector<double>, std::vector<int>>> toUnorderedMap(const std::map<std::vector<int>, std::pair<std::vector<double>, std::vector<int>>>& map) {
    std::unordered_map<std::vector<int>, std::pair<std::vector<double>, std::vector<int>>> unorderedMap;
    for (const auto& entry : map) {
        unorderedMap.insert(entry);
    }
    return unorderedMap;
}

报错:

[100%] Built target move_base_node In file included from /usr/include/c++/9/unordered_map:47, from /home/sukai/workspace/workspace_ros_car_noetic/src/trilateration/src/test/test4.cpp:7: /usr/include/c++/9/bits/unordered_map.h: In constructor ‘std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map(_InputIterator, _InputIterator, std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::size_type, const hasher&, const key_equal&, const allocator_type&) [with _InputIterator = __gnu_cxx::__normal_iterator<std::pair<std::vector<int>, std::pair<std::vector<double>, std::vector<int> > >*, std::vector<std::pair<std::vector<int>, std::pair<std::vector<double>, std::vector<int> > > > >; _Key = std::vector<int>; _Tp = std::pair<std::vector<double>, std::vector<int> >; _Hash = std::hash<std::vector<int> >; _Pred = std::equal_to<std::vector<int> >; _Alloc = std::allocator<std::pair<const std::vector<int>, std::pair<std::vector<double>, std::vector<int> > > >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::size_type = long unsigned int; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hasher = std::hash<std::vector<int> >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_equal = std::equal_to<std::vector<int> >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::allocator_type = std::allocator<std::pair<const std::vector<int>, std::pair<std::vector<double>, std::vector<int> > > >]’: /usr/include/c++/9/bits/unordered_map.h:174:30: error: use of deleted function ‘std::hash<std::vector<int> >::hash()’ 174 | const hasher& __hf = hasher(), | ^~~~~~~~

这个自定义哈希函数是用在 std::unordered_mapstd::unordered_set 中,用于将 std::vector<int> 作为键来存储和查找值。这对于存储多边形的顶点组合特别有用,因为 std::vector<int> 默认没有提供哈希函数。

为了解决这个问题,需要手动定义一个哈希函数,并指定给 std::unordered_map 使用。下面是一个简单的哈希函数的示例:

namespace std {
    template <>
    struct hash<std::vector<int>> {
        size_t operator()(const std::vector<int>& v) const {
            size_t hash = 0;
            for (int i : v) {
                hash ^= std::hash<int>{}(i) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
            }
            return hash;
        }
    };
}

还需要定义一个相等比较器来确保 std::unordered_map 正确工作。下面是一个简单的相等比较器的示例:

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

然后,可以将这个相等比较器用作 std::unordered_map 的第四个模板参数。

std::unordered_map<std::vector<int>, std::pair<std::vector<double>, std::vector<int>>, std::hash<std::vector<int>>, VectorIntEqual> unorderedMap;

std::unordered_map<std::vector<int>, std::tuple<std::vector<double>, std::vector<double>, std::vector<int>>, VectorIntEqual> edgeMap;

// 当插入元素时:
std::vector<int> combo = {1, 2, 3, 4};
std::vector<double> edges = {1.0, 2.0, 3.0, 4.0};
std::vector<double> angles = {0.5, 0.5, 0.5, 0.5};
edgeMap[combo] = std::make_tuple(edges, angles, combo);

// 当查找元素时:
if (edgeMap.find(combo) != edgeMap.end()) {
    auto [storedEdges, storedAngles, storedCombo] = edgeMap[combo];
    // 使用 storedEdges, storedAngles, storedCombo
}
std::unordered_map<std::vector<int>, std::pair<std::vector<double>, std::vector<int>>, VectorIntEqual> toUnorderedMap(const std::map<std::vector<int>, std::pair<std::vector<double>, std::vector<int>>, VectorIntEqual>& map) {
    std::unordered_map<std::vector<int>, std::pair<std::vector<double>, std::vector<int>>, VectorIntEqual> unorderedMap;
    for (const auto& entry : map) {
        unorderedMap.insert(entry);
    }
    return unorderedMap;
}

在调用 toUnorderedMap 函数时,需要传递 VectorIntEqual 的实例作为第五个参数

auto unorderedMap = toUnorderedMap(map, VectorIntEqual{});

std::vector<std::string> 定义一个自定义哈希函数和相等比较器

  1. 定义哈希函数: 为 std::vector<std::string> 编写一个哈希函数。

  2. 定义相等比较器: 编写一个相等比较器来比较两个 std::vector<std::string> 是否相等。

下面是完整的代码示例,展示如何定义这些组件并使用 std::vector<std::string> 作为 std::unordered_map 的键:

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <functional>

// 定义哈希函数
namespace std {
    template <>
    struct hash<std::vector<std::string>> {
        size_t operator()(const std::vector<std::string>& v) const {
            size_t hash = 0;
            for (const auto& str : v) {
                hash ^= std::hash<std::string>{}(str) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
            }
            return hash;
        }
    };
}

// 定义相等比较器
struct VectorStringEqual {
    bool operator()(const std::vector<std::string>& a, const std::vector<std::string>& b) const {
        return a == b;
    }
};

int main() {
    // 创建一个使用 vector<string> 作为键的 unordered_map
    std::unordered_map<std::vector<std::string>, int, std::hash<std::vector<std::string>>, VectorStringEqual> myMap;

    // 插入元素
    std::vector<std::string> key1 = {"hello", "world"};
    std::vector<std::string> key2 = {"foo", "bar"};
    myMap[key1] = 1;
    myMap[key2] = 2;

    // 查找元素
    if (myMap.find(key1) != myMap.end()) {
        std::cout << "key1 found with value: " << myMap[key1] << std::endl;
    } else {
        std::cout << "key1 not found" << std::endl;
    }

    if (myMap.find(key2) != myMap.end()) {
        std::cout << "key2 found with value: " << myMap[key2] << std::endl;
    } else {
        std::cout << "key2 not found" << std::endl;
    }

    return 0;
}

换一种:

// 自定义哈希函数和相等比较器
struct VectorStringHash {
    std::size_t operator()(const std::vector<std::string>& vec) const {
        std::size_t hash = 0;
        for (const auto& str : vec) {
            hash ^= std::hash<std::string>()(str) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
        }
        return hash;
    }
};

struct VectorStringEqual {
    bool operator()(const std::vector<std::string>& lhs, const std::vector<std::string>& rhs) const {
        return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
    }
};


    std::unordered_map<std::vector<std::string>, std::vector<std::tuple<std::vector<double>, std::vector<std::vector<std::shared_ptr<ReflectorPanelPoint> >>>>,VectorStringHash, VectorStringEqual> unorderedEdgeMapNew_IdKey;


//增加数据:
                unorderedEdgeMapNew_IdKey[std::vector<std::string>{point1->id, point2->id}].emplace_back(std::make_tuple(std::vector<double>{distance},std::vector<std::vector<std::shared_ptr<ReflectorPanelPoint>>>{{point1, point2}}));


//遍历数据:
  // 遍历 unorderedEdgeMapNew_IdKey,打印数据
    for (const auto& pair : unorderedEdgeMapNew_IdKey) {
        std::cout << "Key: ";
        for (const auto& str : pair.first) {
            std::cout << str << " ";
        }
        std::cout << std::endl;

        // 打印值
        for (const auto& tuple : pair.second) {
            const auto& innerVec1 = std::get<0>(tuple);
            const auto& innerVec2 = std::get<1>(tuple);
            
            std::cout << "  Tuple - Vector 1: ";
            for (const auto& value : innerVec1) {
                std::cout << value << " ";
            }
            std::cout << std::endl;

            std::cout << "  Tuple - Vector 2: ";
            for (const auto& innerVec : innerVec2) {
                std::cout << "[ ";
                for (const auto& ptr : innerVec) {
                    // 使用 ptr 指针
                }
                std::cout << "] ";
            }
            std::cout << std::endl;
        }
    }



//==========================================================

/*





#include <vector>
#include <unordered_map>
#include <tuple>
#include <cmath>
#include <iostream>
#include <queue>
#include <map>
//uuid
#include <chrono>
#include <random>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <thread>
#include <atomic>
#include <mutex>
//#include <algorithm> // 添加这一行以包含 std::sort
//#include <memory>
/**
 *
 *  通过两点中的边长匹配反光板id
 *  可用递归
 * @param edge1
 * @param edge2
 * @param threshold
 * @return
 */
struct Point {
    double x, y;
};

#ifndef REFLECTOR_PANEL_POINT_H
#define REFLECTOR_PANEL_POINT_H
class ReflectorPanelPoint {
public:
    std::string id="EMPTY";//唯一标示
    std::string shape="EMPTY";//CUBE:立方体(平面),CYLINDER: 圆柱体
    std::string source_frame_id="map";//地图坐标系
    std::string target_frame_id="base_link";//雷达坐标系
    double range=0.0;
    double intensity=0.0;
    double x=0.0, y=0.0, z=0.0;
    double rx=0.0, ry=0.0, rz=0.0, rw=1.0;

    double scan_x=0.0, scan_y=0.0, scan_z=0.0;
    double scan_rx=0.0, scan_ry=0.0, scan_rz=0.0, scan_rw=1.0;

    double angle=0.0;//计算target_frame_id坐标系下的角度 scan_x=0.0, scan_y=0.0, scan_z
    double distances=0.0;//计算target_frame_id坐标系下 rx=0.0, ry=0.0, rz=0.0, rw=1.0 欧几里德距离

    //private:
   // tf::TransformListener tf_listener;
    //线程多
    std::atomic<bool> should_stop{false}; // 用于线程停止的信号
    std::thread transform_thread;
    explicit ReflectorPanelPoint(const std::string& id);
    explicit ReflectorPanelPoint(const std::string& id, double x, double y, double z, double rx, double ry, double rz, double rw);

    ReflectorPanelPoint();

    ~ReflectorPanelPoint() {
       // stopTransformThread();
    }

public:
    static std::unordered_map<std::string, std::shared_ptr<ReflectorPanelPoint>> instances;
    static std::mutex instance_mutex;

    static std::shared_ptr<ReflectorPanelPoint> createInstance1(const std::string& id);
    static std::shared_ptr<ReflectorPanelPoint> createInstance2(const std::string& id, double x, double y, double z, double rx, double ry, double rz, double rw);

    void startTransformThread(); // Assuming this function is defined elsewhere
    void stopTransformThread();

   // void transformAndCalculate(const ros::Time& time);
    void transformThreadFunc();

    friend std::ostream& printPoint(std::ostream& os,const std::shared_ptr<ReflectorPanelPoint> &point) {
        //打印数据
//    std::cout << "ReflectorPanelPoint shared_point1 :\n";
//    printPoint(std::cout, shared_point1);
//    std::cout << std::endl;
        os << "ReflectorPanelPoint =》 "
           << ", ID: " << point->id << ", Shape: " << point->shape
           << ", Range: " << point->range << ", Intensity: " << point->intensity
           << ", source_frame_id: " << point->source_frame_id
           << ", source_Position: (" << point->x << ", " << point->y << ", " << point->z << ")"
           << ", source_Orientation: (" << point->rx << ", " << point->ry << ", " << point->rz << ", " << point->rw << ")"
           << ", target_frame_id: " << point->target_frame_id
           << ", target_Position: (" << point->scan_x << ", " << point->scan_y << ", " << point->scan_z << ")"
           << ", target_Orientation: (" << point->scan_rx << ", " << point->scan_ry << ", " << point->scan_rz << ", " << point->scan_rw << ")"
           << ", Angle: " << point->angle << ", Distances: " << point->distances;
        return os;
    }

//直接用 cout<<point<<打印
    friend std::ostream& operator<<(std::ostream& os,const std::shared_ptr<ReflectorPanelPoint> &point) {
        os << "ReflectorPanelPoint =》 "
           << ", ID: " << point->id << ", Shape: " << point->shape
           << ", Range: " << point->range << ", Intensity: " << point->intensity
           << ", source_frame_id: " << point->source_frame_id
           << ", source_Position: (" << point->x << ", " << point->y << ", " << point->z << ")"
           << ", source_Orientation: (" << point->rx << ", " << point->ry << ", " << point->rz << ", " << point->rw << ")"
           << ", target_frame_id: " << point->target_frame_id
           << ", target_Position: (" << point->scan_x << ", " << point->scan_y << ", " << point->scan_z << ")"
           << ", target_Orientation: (" << point->scan_rx << ", " << point->scan_ry << ", " << point->scan_rz << ", " << point->scan_rw << ")"
           << ", Angle: " << point->angle << ", Distances: " << point->distances;
        return os;
    }


};

#endif // REFLECTOR_PANEL_POINT_H
//--------------------------------------------------------------------------------------

// 在 .cpp 文件中定义静态成员变量
std::unordered_map<std::string, std::shared_ptr<ReflectorPanelPoint>> ReflectorPanelPoint::instances;
std::mutex ReflectorPanelPoint::instance_mutex;
ReflectorPanelPoint::ReflectorPanelPoint() {}
ReflectorPanelPoint::ReflectorPanelPoint(const std::string& id): id(id) {}
ReflectorPanelPoint::ReflectorPanelPoint(const std::string& id, double x, double y, double z, double rx, double ry, double rz, double rw):id(id), x(x), y(y), z(z), rx(rx), ry(ry), rz(rz), rw(rw) {}

// 初始化静态成员
std::shared_ptr<ReflectorPanelPoint> ReflectorPanelPoint::createInstance1(const std::string& id) {
    std::lock_guard<std::mutex> lock(instance_mutex);
    auto it = instances.find(id);
    if (it == instances.end()) {
        auto new_point = std::make_shared<ReflectorPanelPoint>(id);
        instances[id] = new_point;
        instances[id]->startTransformThread();
        return new_point;
    }
    return it->second;
}
// 初始化静态成员
std::shared_ptr<ReflectorPanelPoint> ReflectorPanelPoint::createInstance2(const std::string& id, double x, double y, double z,double  rx, double ry, double rz, double rw) {
    std::lock_guard<std::mutex> lock(instance_mutex);
    auto it = instances.find(id);
    if (it == instances.end()) {
        auto new_point = std::make_shared<ReflectorPanelPoint>(id,  x,  y,  z,  rx,  ry,  rz,  rw);
        instances[id] = new_point;
        instances[id]->startTransformThread();
        return new_point;
    }
    return it->second;
}

void ReflectorPanelPoint::startTransformThread() {
    if (!transform_thread.joinable()) {
      //  transform_thread = std::thread(&ReflectorPanelPoint::transformThreadFunc, this);
    }
}

void ReflectorPanelPoint::stopTransformThread() {
    if (transform_thread.joinable()) {
        should_stop.store(true);
        transform_thread.join();
    }
}
/**
void ReflectorPanelPoint::transformThreadFunc() {
    while (!should_stop.load()) {
        transformAndCalculate(ros::Time::now());
        // 根据需要添加适当的延时,例如 10ms
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
    }
}
void ReflectorPanelPoint::transformAndCalculate(const ros::Time& time) {
    try {
        // std::cout<<"111111111111111111111111111111111111111"<<std::endl;
        // 获取从 source_frame_id 到 target_frame_id 的转换
        tf::StampedTransform transform;
        // 等待变换数据,最多等待1秒
        tf_listener.waitForTransform(target_frame_id, source_frame_id,
                                     ros::Time(0), ros::Duration(1.0));
        tf_listener.lookupTransform(target_frame_id, source_frame_id, time, transform);

        // 将坐标从 source_frame_id 转换到 target_frame_id
        tf::Vector3 source_point(x, y, z);
        tf::Vector3 target_point = transform * source_point;
        // 计算欧几里得距离
        distances = target_point.length();
        // 计算角度
        angle = atan2(target_point.y(), target_point.x());

        // 设置旋转坐标
        tf::Quaternion target_quaternion = tf::Quaternion(transform.getRotation());
        scan_rx = target_quaternion.getX();
        scan_ry = target_quaternion.getY();
        scan_rz = target_quaternion.getZ();
        scan_rw = target_quaternion.getW();

        // 设置位置坐标
        scan_x = target_point.x();
        scan_y = target_point.y();
        scan_z = target_point.z();


    } catch (tf::TransformException& ex) {
        ROS_ERROR("tf  %s", ex.what());
    }
}
*/

//=========================================================================================
// 简化的10位字符串生成器
std::string generate_shortened_string() {
    // 获取当前时间(秒精度)
    auto now = std::chrono::system_clock::now();
    auto time_point_s = std::chrono::time_point_cast<std::chrono::seconds>(now);
    uint32_t timestamp = time_point_s.time_since_epoch().count();

    // 添加随机数
    std::random_device rd;
    std::mt19937 gen(rd());

    // 产生一个0-25之间的随机数,对应字母'A'到'Z'
    std::uniform_int_distribution<> letter_dis(0, 25);
    char random_letter = 'A' + letter_dis(gen);

    // 产生一个0-999999之间的随机数
    std::uniform_int_distribution<> dis(0, 999999);

    std::stringstream ss;//#include <sstream>
    // 首字符为随机大写字母,后面跟上原本的5-5格式数字
    ss << random_letter
       << std::uppercase << std::hex << std::setw(5) << std::setfill('0') << timestamp
       << std::hex << std::setw(5) << std::setfill('0') << dis(gen);
    return ss.str();
}
//===========================================================================




**/


//====================================================================

std::unordered_map 中对比 std::vector<double> 的值,可以通过自定义的相等比较器来实现。这在标准库中是没有直接提供的,需要你自己实现。

下面是一个示例,其中 std::unordered_map 的键是 std::vector<std::string>,值是 std::vector<double>,并且包含自定义的哈希函数和相等比较器来对比 std::vector<double> 的值。

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <functional>
#include <cmath>
 // 设定一个小的容忍值来
double equalDoubleThreshold_=1e-9;
// 定义哈希函数
namespace std {
    template <>
    struct hash<std::vector<std::string>> {
        size_t operator()(const std::vector<std::string>& v) const {
            size_t hash = 0;
            for (const auto& str : v) {
                hash ^= std::hash<std::string>{}(str) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
            }
            return hash;
        }
    };

    template <>
    struct hash<std::vector<double>> {
        size_t operator()(const std::vector<double>& v) const {
            size_t hash = 0;
            for (const auto& num : v) {
                hash ^= std::hash<double>{}(num) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
            }
            return hash;
        }
    };
}

// 定义相等比较器
struct VectorStringEqual {
    bool operator()(const std::vector<std::string>& a, const std::vector<std::string>& b) const {
        return a == b;
    }
};

struct VectorDoubleEqual {
    bool operator()(const std::vector<double>& a, const std::vector<double>& b) const {
        if (a.size() != b.size()) return false;
        for (size_t i = 0; i < a.size(); ++i) {
            if (std::fabs(a[i] - b[i]) > equalDoubleThreshold_) return false; // 设定一个小的容忍值来比较浮点数
        }
        return true;
    }
};

int main() {
    // 创建一个使用 vector<string> 作为键,vector<double> 作为值的 unordered_map
    std::unordered_map<std::vector<std::string>, std::vector<double>, std::hash<std::vector<std::string>>, VectorStringEqual> myMap;

    // 插入元素
    std::vector<std::string> key1 = {"hello", "world"};
    std::vector<double> value1 = {1.0, 2.0, 3.0};
    std::vector<std::string> key2 = {"foo", "bar"};
    std::vector<double> value2 = {4.0, 5.0, 6.0};
    myMap[key1] = value1;
    myMap[key2] = value2;

    // 查找元素并对比值
    std::vector<double> targetValue = {1.0, 2.0, 3.0};
    bool found = false;

    for (const auto& pair : myMap) {
        if (VectorDoubleEqual{}(pair.second, targetValue)) {
            found = true;
            std::cout << "匹配的键为: ";
            for (const auto& str : pair.first) {
                std::cout << str << " ";
            }
            std::cout << std::endl;
            break;
        }
    }

    if (!found) {
        std::cout << "未找到匹配的值" << std::endl;
    }

    return 0;
}

std::unordered_map 中使用 std::vector<double> 作为键,需要自定义哈希函数和相等比较器。这些自定义类型用于计算 std::vector<double> 的哈希值,并定义两个 std::vector<double> 是否相等。以下是一个示例代码:

#include <iostream>
#include <vector>
#include <unordered_map>
#include <cmath>
 // 设定一个小的容忍值来
double equalDoubleThreshold_=1e-9;
// 定义哈希函数
namespace std {
    template <>
    struct hash<std::vector<double>> {
        size_t operator()(const std::vector<double>& v) const {
            size_t hash = 0;
            for (const auto& num : v) {
                hash ^= std::hash<double>{}(num) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
            }
            return hash;
        }
    };
}

// 定义相等比较器
struct VectorDoubleEqual {
    bool operator()(const std::vector<double>& a, const std::vector<double>& b) const {
        if (a.size() != b.size()) return false;
        for (size_t i = 0; i < a.size(); ++i) {
            if (std::fabs(a[i] - b[i]) > equalDoubleThreshold_) return false; // 设定一个小的容忍值来比较浮点数
        }
        return true;
    }
};

int main() {
    // 创建一个使用 vector<double> 作为键,int 作为值的 unordered_map
    std::unordered_map<std::vector<double>, int, std::hash<std::vector<double>>, VectorDoubleEqual> myMap;

    // 插入元素
    std::vector<double> key1 = {1.0, 2.0, 3.0};
    int value1 = 10;
    std::vector<double> key2 = {4.0, 5.0, 6.0};
    int value2 = 20;
    myMap[key1] = value1;
    myMap[key2] = value2;

    // 查找元素
    std::vector<double> targetKey = {1.0, 2.0, 3.0};
    auto it = myMap.find(targetKey);
    if (it != myMap.end()) {
        std::cout << "找到的值为: " << it->second << std::endl;
    } else {
        std::cout << "未找到匹配的键" << std::endl;
    }

    return 0;
}

现在,myMap使用double作为键,int作为值。哈希函数和相等比较器针对单个double进行了优化,请注意,使用这种方法可能会导致精度相关的意外行为,因为浮点数的哈希可能会受到浮点不精确性的影响。在某些情况下,两个看似相等的double可能会得到不同的哈希值。然而,在大多数简单场景下,这个实现应该足够用了。

// 定义哈希函数
namespace std {
    template <>
    struct hash<double> {
        size_t operator()(const double& d) const {
            return std::hash<long long>()(*reinterpret_cast<const long long*>(&d));
        }
    };
}

// 定义相等比较器
struct DoubleEqual {
    bool operator()(const double& a, const double& b) const {
        return std::fabs(a - b) <= equalDoubleThreshold_;
    }
};

int main() {
    // 创建一个使用 double 作为键,int 作为值的 unordered_map
    std::unordered_map<double, int, std::hash<double>, DoubleEqual> myMap;

    // 插入元素
    double key1 = 1.0;
    int value1 = 10;
    double key2 = 4.0;
    int value2 = 20;
    myMap[key1] = value1;
    myMap[key2] = value2;

    // 查找元素
    double targetKey = 1.0;
    auto it = myMap.find(targetKey);
    if (it != myMap.end()) {
        std::cout << "找到的值为: " << it->second << std::endl;
    } else {
        std::cout << "未找到匹配的键" << std::endl;
    }

    return 0;
}

为了避免浮点不精确性导致的问题,可以使用一个基于字符串表示的哈希函数。这种方法将double转换为其文本表示,然后对字符串进行哈希。同时,比较器仍然使用绝对误差检查。以下是修改后的代码:

#include <iostream>
#include <unordered_map>
#include <cmath>
#include <sstream>

// 设定一个小的容忍值来
double equalDoubleThreshold_ = 1e-9;

// 定义哈希函数
namespace std {
    template <>
    struct hash<double> {
        size_t operator()(const double& d) const {
            std::ostringstream oss;
            oss << d;
            return std::hash<std::string>()(oss.str());
        }
    };
}

// 定义相等比较器
struct DoubleEqual {
    bool operator()(const double& a, const double& b) const {
        return std::fabs(a - b) <= equalDoubleThreshold_;
    }
};

int main() {
    // 创建一个使用 double 作为键,int 作为值的 unordered_map
    std::unordered_map<double, int, std::hash<double>, DoubleEqual> myMap;

    // 插入元素
    double key1 = 1.0;
    int value1 = 10;
    double key2 = 4.0;
    int value2 = 20;
    myMap[key1] = value1;
    myMap[key2] = value2;

    // 查找元素
    double targetKey = 1.0;
    auto it = myMap.find(targetKey);
    if (it != myMap.end()) {
        std::cout << "找到的值为: " << it->second << std::endl;
    } else {
        std::cout << "未找到匹配的键" << std::endl;
    }

    return 0;
}

自定义double作为键,int作为值。哈希函数和相等比较器针对单个double进行了优化

#include <iostream>
#include <unordered_map>
#include <functional>
#include <cmath>

double equalDoubleDistanceThreshold_=0.1; // 1e-9
double equalDoubleAngleThreshold_=0.1;
// 自定义哈希函数
struct MyDoubleHash {
    std::size_t operator()(const double&  val) const {
        // 你的自定义哈希算法
       //return std::hash<std::string>()(std::to_string(val));
     //   return std::hash<long long>()(*reinterpret_cast<const long long*>(&val));
        // 将double值四舍五入到给定的精度范围内,然后再进行哈希
       // int roundedVal = static_cast<int>(std::round(val * 10)); // 例如,这里是保留一位小数
        int roundedVal = static_cast<int>(std::round(val* 10 )); // 例如,这里是保留一位小数
        return std::hash<int>()(roundedVal);

    }
};


// 自定义比较器
struct MyDoubleEqual {
    double threshold;

    MyDoubleEqual(const double&  t) : threshold(t) {}

    bool operator()(const double&  lhs, const double&  rhs) const {
        // 你的自定义比较逻辑
        return std::fabs(lhs - rhs) < threshold;  // 使用传递的阈值
    }
};

int main() {
    // 使用自定义哈希函数和比较器的unordered_map
 //   std::unordered_map<double, int, MyDoubleHash, MyDoubleEqual> myMap;
    // 使用自定义哈希函数和比较器的unordered_map
    std::unordered_map<double, int, MyDoubleHash, MyDoubleEqual> myMap(10, MyDoubleHash(), MyDoubleEqual(equalDoubleDistanceThreshold_));

    // 插入一些值
    // 插入一些值
    myMap[3.14] = 1;
    myMap[3.12159] = 9;
    myMap[2.71828] = 2;
    myMap[1.61803] = 3;

    // 访问值
    std::cout << "Value for 3.14159: " << myMap[3.14159] << std::endl;
    std::cout << "Value for 2.71828: " << myMap[2.71828] << std::endl;
    std::cout << "-------------------------------------"  << std::endl;
    // 测试比较器的效果
    double key = 2.8183;
    if (myMap.find(key) != myMap.end()) {
        std::cout << "Found value for key: " << key <<" ,value: "  <<myMap[key]<<std::endl;
    } else {
        std::cout << "error Value not found for " << key <<" ,value: "  <<myMap[key]<< std::endl;
    }

    std::cout << "-------------------------------------"  << std::endl;

    // 使用范围 for 循环遍历所有数据
    std::cout << "Using range-based for loop:" << std::endl;
    for (const auto& pair : myMap) {
        std::cout << "Key: " << pair.first << ", Value: " << pair.second << std::endl;
    }
    std::cout << "-------------------------------------"  << std::endl;

    // 使用迭代器遍历所有数据
    std::cout << "\nUsing iterator:" << std::endl;
    for (auto it = myMap.begin(); it != myMap.end(); ++it) {
        std::cout << "Key: " << it->first << ", Value: " << it->second << std::endl;
    }
    std::cout << "-------------------------------------"  << std::endl;


    return 0;
}

  • 13
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
std::vectorstd::unordered_map是C++标准库的两种不同类型的容器,它们有以下区别: 1. 数据结构: - std::vector是一个动态数组,它在内存以连续的方式存储元素。这使得std::vector支持随机访问,即可以通过索引快速访问任何元素。 - std::unordered_map是一个哈希表,它使用哈希函数将映射到存储桶。这使得std::unordered_map支持通过快速查找值,但不支持随机访问。 2. 插入和删除操作: - std::vector在尾部插入和删除元素的时间复杂度为O(1),但在间或开头插入和删除元素的时间复杂度为O(n)。 - std::unordered_map在插入和删除元素时的平均时间复杂度为O(1)。 3. 元素的顺序: - std::vector的元素按照它们被插入的顺序进行存储,并且可以通过索引进行访问。 - std::unordered_map的元素没有特定的顺序,它们根据哈希函数的结果进行存储。 4. 内存占用: - std::vector在内存以连续的方式存储元素,因此它的内存占用比较紧凑。 - std::unordered_map使用哈希表来存储元素,因此它的内存占用可能比较大。 下面是一个演示std::vectorstd::unordered_map的例子: ```cpp #include <iostream> #include <vector> #include <unordered_map> int main() { // 使用std::vector存储整数 std::vector<int> vec = {1, 2, 3, 4, 5}; // 使用std::unordered_map存储值对 std::unordered_map<std::string, int> map = {{"apple", 1}, {"banana", 2}, {"orange", 3}}; // 访问std::vector的元素 std::cout << "Vector element at index 2: " << vec[2] << std::endl; // 访问std::unordered_map的元素 std::cout << "Value of 'banana': " << map["banana"] << std::endl; return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_无往而不胜_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值