std::map、std::set使用自定义数据的键值时注意排序

map、set插入自定义数据类型作为key时需要注意什么问题问题?!!!!!!!!
首先要解决排序问题,方法有:
1.重载自定义数据类型的operator<()操作符

2.map类型的第三个参数为函数对象类类型,可以自定义这个比较函数的函数对象,
  如申明一个类似
  struct CustomLess
  {
      bool operator()(const CustomKey2& other1, const CustomKey2& other2)
      {
      return other1.a < other2.a || (other1.a == other2.a && other1.b < other2.b);
      }
  };
  的函数对象,将其作为map申明类型的第三个参数类型传入

3.利用std::function封装一个
  typedef std::function<bool(const CustomKey2&, const CustomKey2&)> FuncType;
  将FuncType作为map的第三个参数,并在定义map对象时传入一个FuncType的可执行体,如对对应的普通函数指针,函数对象,Lambda表达式等

4.对map的第三个参数类型less函数的进行模板定制-可以全特化
  模板特化匹配优先级:全特化 > 偏特化 > 主模板

#include <map>
#include <string>
#include <iostream>
#include <functional>

using namespace std;

/************************************************************************/
/* 
map、set插入自定义数据类型作为key时需要注意什么问题问题?!!!!!!!!
首先要解决排序问题,方法有:
1.重载自定义数据类型的operator<()操作符

2.map类型的第三个参数为函数对象类类型,可以自定义这个比较函数的函数对象,
  如申明一个类似
  struct CustomLess
  {
	  bool operator()(const CustomKey2& other1, const CustomKey2& other2)
	  {
	  return other1.a < other2.a || (other1.a == other2.a && other1.b < other2.b);
	  }
  };
  的函数对象,将其作为map申明类型的第三个参数类型传入

3.利用std::function封装一个
  typedef std::function<bool(const CustomKey2&, const CustomKey2&)> FuncType;
  将FuncType作为map的第三个参数,并在定义map对象时传入一个FuncType的可执行体,如对对应的普通函数指针,函数对象,Lambda表达式等

4.对map的第三个参数类型less函数的进行模板定制-可以全特化
  模板特化匹配优先级:全特化 > 偏特化 > 主模板
*/
/************************************************************************/

/*
std::map类型的定义头部模板参数

template<class _Kty,
class _Ty,
class _Pr = less<_Kty>,
class _Alloc = allocator<pair<const _Kty, _Ty> > >

第1个参数存储了key。
第2个参数存储了mapped value。
第3个参数是比较函数的函数对象。map用它来判断两个key的大小,并返回bool类型的结果。利用这个函数,map可以确定元素在容器中遵循的顺序以及两个元素键是否相等(!comp(a,b)&&!comp(b,a)),确保map中没有两个元素可以具有等效键。这里,它的默认值是less<Key>,定义如下

std::map的部分构造函数:

map()
: _Mybase(key_compare())
{	// construct empty map from defaults
}

// 入参时比较函数或对象
explicit map(const key_compare& _Pred)
: _Mybase(_Pred)
{	// construct empty map from comparator
}

// map默认比较函数对象 less<_Kty>
template<class _Ty = void>
	struct less
	{	// functor for operator<
	typedef _Ty first_argument_type;
	typedef _Ty second_argument_type;
	typedef bool result_type;

	constexpr bool operator()(const _Ty& _Left, const _Ty& _Right) const
	{	// apply operator< to operands
	return (_Left < _Right);
	}
	};

*/

// 自定义数据key
struct CustomKey1
{
	CustomKey1()
	{}

	CustomKey1(int ai, int bi): a(ai), b(bi)
	{}

	// 方法1,重写<操作符
	bool operator<(const CustomKey1& other) const // 注意这里的两个const
	{
		return a < other.a || (a == other.a && b < other.b);
	}

	int a = 1;
	int b = 2;
};

// 测试重载<操作符
void Test_Operator_CustomKey1()
{
	std::map<CustomKey1, int> mapCustomKeyInt;
	mapCustomKeyInt.insert(std::make_pair(CustomKey1(1, 2), 1));
	mapCustomKeyInt.insert(std::make_pair(CustomKey1(1, 3), 1));
}

struct CustomKey2
{
	CustomKey2()
	{}

	CustomKey2(int ai, int bi) : a(ai), b(bi)
	{}

	int a = 1;
	int b = 2;
};

// 2.将map类型的第三个参数函数对象类型重写
struct CustomLess
{
	bool operator()(const CustomKey2& other1, const CustomKey2& other2)
	{
		return other1.a < other2.a || (other1.a == other2.a && other1.b < other2.b);
	}
};

// 将map类型的第三个参数函数对象类型重写
void Test_CustomLess()
{
	std::map<CustomKey2, int, CustomLess> mapCustomKeyInt;
	/*CustomLess c;
	std::map<CustomKey2, int, CustomLess> mapCustomKeyInt(c);*/ // 也可以传入CustomLess这个可执行对象
	mapCustomKeyInt.insert(std::make_pair(CustomKey2(1, 2), 1));
	mapCustomKeyInt.insert(std::make_pair(CustomKey2(1, 3), 1));
}

// 3.使用std::function 将 一个可以比较的函数或函数对象打包生成一个可调用对象
bool CompareFunc(const CustomKey2& other1, const CustomKey2& other2) // 普通函数
{
	return other1.a < other2.a || (other1.a == other2.a && other1.b < other2.b);
}

void Test_CompareFunc()
{
	typedef std::function<bool(const CustomKey2&, const CustomKey2&)> FuncType;
	std::map<CustomKey2, int, FuncType> mapCustomKeyInt(CompareFunc);
	mapCustomKeyInt.insert(std::make_pair(CustomKey2(1, 2), 1));
	mapCustomKeyInt.insert(std::make_pair(CustomKey2(1, 3), 1));
}

//4.全特化map默认的比较函数对象less
template<>
struct std::less <CustomKey2>
{	// functor for operator<
	bool operator()(const CustomKey2& other1, const CustomKey2& other2) // 普通函数
	{
		return other1.a < other2.a || (other1.a == other2.a && other1.b < other2.b);
	}
};

void Test_less()
{
	std::map<CustomKey2, int> mapCustomKeyInt;
	mapCustomKeyInt.insert(std::make_pair(CustomKey2(1, 2), 1));
	mapCustomKeyInt.insert(std::make_pair(CustomKey2(1, 3), 1));
}

int main()
{
	Test_Operator_CustomKey1();
	Test_CustomLess();
	Test_CompareFunc();
	Test_less();

	getchar();
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
std::mapstd::set是常用的关联式容器,它们都是ADT(抽象数据类型)。它们的接口不仅规定了操作的功能,还规定了操作的复杂度。例如,std::map的insert函数在通常情况下的复杂度是O(logN),其中N是元素的数量。但是如果插入的元素已经按照键值排序,那么复杂度将会是O(1)。\[1\] 在实现中,为了节约std::mapstd::set对象的大小,STL使用了空基类优化。具体做法是将rb_tree作为成员变量,而rb_tree又以rb_tree_impl为成员变量,rb_tree_impl继承自allocator。如果allocator是空类,那么rb_tree_impl的大小就和没有基类一样。其他STL容器也使用了相同的优化措施,因此std::vector对象占用3个字长,std::list对象占用2个字长。boost的compressed_pair也使用了相同的优化。\[2\] 对于传递参数的方式,根据《Effective C++》的建议,我们应该尽量使用const引用来传递对象。但是对于内置类型、STL迭代器和STL仿函数,传值也是可以的,一般不会有性能损失。\[3\] #### 引用[.reference_title] - *1* *2* *3* [关于 std::set/std::map 的几个为什么](https://blog.csdn.net/Solstice/article/details/8521946)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值