1. 概述

STL中像set和map这样的容器是通过红黑树来实现的,插入到容器中的对象是顺序存放的,采用这样的方式是非常便于查找的,查找效率能够达到O(log n)。所以如果有查找数据的需求,可以采用set或者map。

但是我们自定义的结构体或者类,无法对其比较大小,在放入到容器中的时候,就无法正常编译通过,这是set/map容器的规范决定的。要将自定义的结构体或者类存入到set/map容器,就需要定义一个排序的规则,使其可以比较大小。最简单的办法就是在结构体或者类中加入一个重载小于号的成员函数,这样在存数据进入set/map中时,就可以根据其规则排序。

2. 实例

在这里就写了一个简单的例子,将自定义的一个二维点存入set/map,并查找其中存入的数据:

#include <iostream>
#include <map>
#include <set>
#include <string> using namespace std; const double EPSILON = 0.000001; // 2D Point
struct Vector2d
{
public:
Vector2d()
{
} Vector2d(double dx, double dy)
{
x = dx;
y = dy;
} // 矢量赋值
void set(double dx, double dy)
{
x = dx;
y = dy;
} // 矢量相加
Vector2d operator + (const Vector2d& v) const
{
return Vector2d(x + v.x, y + v.y);
} // 矢量相减
Vector2d operator - (const Vector2d& v) const
{
return Vector2d(x - v.x, y - v.y);
} //矢量数乘
Vector2d Scalar(double c) const
{
return Vector2d(c*x, c*y);
} // 矢量点积
double Dot(const Vector2d& v) const
{
return x * v.x + y * v.y;
} //向量的模
double Mod() const
{
return sqrt(x * x + y * y);
} bool Equel(const Vector2d& v) const
{
if (abs(x - v.x) < EPSILON && abs(y - v.y) < EPSILON)
{
return true;
}
return false;
} bool operator == (const Vector2d& v) const
{
if (abs(x - v.x) < EPSILON && abs(y - v.y) < EPSILON)
{
return true;
}
return false;
} bool operator < (const Vector2d& v) const
{
if (abs(x - v.x) < EPSILON)
{
return y < v.y ? true : false;
}
return x<v.x ? true : false;
} double x, y;
}; int main()
{
{
set<Vector2d> pointSet;
pointSet.insert(Vector2d(0, 11));
pointSet.insert(Vector2d(27, 63));
pointSet.insert(Vector2d(27, 15));
pointSet.insert(Vector2d(0, 0));
pointSet.insert(Vector2d(67, 84));
pointSet.insert(Vector2d(52, 63)); for (const auto &it : pointSet)
{
cout << it.x << '\t' << it.y << endl;
} auto iter = pointSet.find(Vector2d(27, 63));
if (iter == pointSet.end())
{
cout << "未找到点" << endl;
}
else
{
cout << "可以找到点" << endl;
}
} {
map<Vector2d, string> pointSet;
pointSet.insert(make_pair(Vector2d(52, 63), "插入时的第1个点"));
pointSet.insert(make_pair(Vector2d(27, 63), "插入时的第2个点"));
pointSet.insert(make_pair(Vector2d(0, 11), "插入时的第3个点"));
pointSet.insert(make_pair(Vector2d(67, 84), "插入时的第4个点"));
pointSet.insert(make_pair(Vector2d(27, 15), "插入时的第5个点"));
pointSet.insert(make_pair(Vector2d(0, 0), "插入时的第6个点")); for (const auto &it : pointSet)
{
cout << it.first.x << ',' << it.first.y << '\t' << it.second << endl;
} auto iter = pointSet.find(Vector2d(27, 63));
if (iter == pointSet.end())
{
cout << "未找到点" << endl;
}
else
{
cout << "可以找到点" << endl;
}
}
}

其中的关键就是在点的结构体中重载了<符号的比较函数,规定首先比较y的大小,其次在比较x的大小:

bool operator < (const Vector2d& v) const
{
if (abs(x - v.x) < EPSILON)
{
return y < v.y ? true : false;
}
return x<v.x ? true : false;
}

最终的运行结果如下:

C++中自定义结构体或类作为关联容器的键的更多相关文章

  1. [转]C#中的结构体与类的区别

    C#中的结构体与类的区别   经常听到有朋友在讨论C#中的结构与类有什么区别.正好这几日闲来无事,自己总结一下,希望大家指点. 1. 首先是语法定义上的区别啦,这个就不用多说了.定义类使用关键字cla ...

  2. 浅析C#中的结构体和类

    类和结构是 .NET Framework 中的常规类型系统的两种基本构造. 两者在本质上都属于数据结构.封装着一组总体作为一个逻辑单位的数据和行为. 数据和行为是该类或结构的"成员" ...

  3. [UE4]自定义结构体、类、数据表

    自定义数据表: #pragma once #include "CoreMinimal.h" #include "Engine/UserDefinedStruct.h&qu ...

  4. C#中的结构体与类的区别

    经常听到有朋友在讨论C#中的结构与类有什么区别.正好这几日闲来无事,自己总结一下,希望大家指点. 1. 首先是语法定义上的区别啦,这个就不用多说了.定义类使用关键字class 定义结构使用关键字str ...

  5. C#中的结构体与类的区别 (转载)

    经常听到有朋友在讨论C#中的结构与类有什么区别.正好这几日闲来无事,自己总结一下,希望大家指点. 1. 首先是语法定义上的区别啦,这个就不用多说了.定义类使用关键字class 定义结构使用关键字str ...

  6. OpenCV中的结构体、类与Emgu.CV的对应表

    OpenCv中的 C 结构 OpenCV中的 C++ 封装 Emgu.CV中的 C# 封装 OpenCV 和 Emgu.CV 中的结构罗列 谢谢阅读,有误希望指正 原文地址 Basic Structu ...

  7. C++ 自定义结构体和类 内存对齐

    为什么要提出内存对齐? 比如这么一种处理器,它每次读写内存的时候都从某个8倍数的地址开始,一次读出或写入8个字节的数据,假如软件能保证double类型的数据都从8倍数地址开始,那么读或写一个doubl ...

  8. C C++ 中结构体与类

    先来说说C和C++中结构体的不同 a) C语言中的结构体不能为空,否则会报错 1>d:\myproject\visual studio 2013\projects\myc++\main.c(71 ...

  9. C++中的结构体

    http://zhidao.baidu.com/link?url=8OYQSKV9mvSBc6Hkf9NsLQmipSge9VCZDJQGAZZs5PCBQ54UTmK98VRmAklEEAFYu7d ...

  10. C语言中的结构体和C++中的结构体以及C++中类的区别

    c++中结构体可以定义一个函数 C中的结构体和C++中结构体的不同之处:在C中的结构体只能自定义数据类型,结构体中不允许有函数,而C++中的结构体可以加入成员函数. C++中的结构体和类的异同: 一. ...

随机推荐

  1. 深入理解Python虚拟机:super超级魔法的背后原理

    深入理解Python虚拟机:super超级魔法的背后原理 在本篇文章中,我们将深入探讨Python中的super类的使用和内部工作原理.super类作为Python虚拟机中强大的功能之一,super ...

  2. linux bond nmcli命令

    基本命令: nmcli connection show 显示所有连接nmcli connection show --active 显示所有活动的连接状态nmcli connection show &q ...

  3. FSCTF 2023(公开赛道)CRYPTO WP

    RSA 1 1.题目信息 提交格式:FSCTF{你所解出的内容} p=1458769258361 q=4556983871563 e=17 求d 2.解题方法 exp from gmpy2 impor ...

  4. MAC版本vmware无法识别虚拟机网卡适配器

    一.问题 莫名其妙的突然mac上的vmware无法识别网络适配器了 二.解决过程 1.重装vmware-无效 2.降级安装vmware-无效 3.安装pd虚拟机,并使用sudo命令启动-偶尔有效 4. ...

  5. 8.12 dp模拟赛总结

    考场概况: 开考发现题目竟然不保证按难度顺序排序QAQ 正序开题, \(T1\) 显然是数位 \(dp\) 然而没学过不会写,顺手打了 \(30pts\) 暴力走人. \(T2\) 期望 \(dp\) ...

  6. 模拟退火算法(SA)

    求某个目标函数的最值 爬山法 首先我们通过爬山法来引出模拟退火算法 我们先看一个例子:求函数的最值 我们用爬山法解决这个问题的步骤 1.在解空间中随机生成一个初始解(图中小黄点就是我们生成的初始解) ...

  7. P5445 [APIO2019] 路灯 题解

    题目链接 题目描述 给你一个 01 串,有 \(q\) 个时刻,每个时刻要么把一位取反,要么问你在过去的所有时刻中有多少个时刻 \(a\) 和 \(b-1\) 之间都为 1. 题目分析 观察题目,我们 ...

  8. 【闭包应用】JS:防抖、节流

    1.防抖:当进行连续操作时,只执行最后一次的操作. //防抖的概念是 当进行连续操作时,只执行最后一次的操作. function debounce(fn, delayTime) { let timeo ...

  9. 聊聊 RocketMQ 消息轨迹

    这篇文章,我们聊一聊 RocketMQ 的消息轨迹设计思路. 查询消息轨迹可作为生产环境中排查问题强有力的数据支持 ,也是研发同学解决线上问题的重要武器之一. 1 基础概念 消息轨迹是指一条消息从生产 ...

  10. simple-check-100

    代码脚本解开法 #include <stdio.h> int main(int argc, char* argv[]) { char flag_data[] = { 220, 23, 19 ...