【STL】 set、map详解

前面已经为大家总结了有关vector,list等的用法(https://blog.csdn.net/yaotengjian/article/details/81706046)。

set:

         set是STL中一种标准关联容器(vector,list,string,deque都是序列容器,而set,multiset,map,multimap是标准关联容器),它底层使用平衡的搜索树——红黑树实现,插入删除操作时仅仅需要指针操作节点即可完成,不涉及到内存移动和拷贝,所以效率比较高。set,顾名思义是“集合”的意思,在set中元素都是唯一的,而且默认情况下会对元素自动进行升序排列,支持集合的交(set_intersection),差(set_difference) 并(set_union),对称差(set_symmetric_difference) 等一些集合上的操作,如果需要集合中的元素允许重复那么可以使用multiset。

        set的一个集合,好比一个袋子里面装了好多个小球。但是红黑树是一种特殊的二叉搜索树,set中的元素根据其值的大小在红黑树中有特定的位置,是不可移动的。所以,1是search操作效率会很高O(log n),2是set中元素的值不可改变。

下面附上简单的代码讲解各部分的接口与功能:

int main()
{
	//创建set对象
	set s{ 1,5,1,6,3,5 };
	set::iterator it;
	for (it = s.begin(); it != s.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;
	//1 3 5 6


//元素的反向遍历  rebegin  rend
	set s{ 6,4,3,5,2,8,3,1, };
	set::reverse_iterator it;
	for (it = s.rbegin(); it != s.rend(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;



//元素的删除
	set s{ 5,1,6,6,3,5,6 };
	set::reverse_iterator it;
	for (it = s.rbegin(); it != s.rend(); ++it)
	{
		cout << *it << endl;
	}
	cout << endl;

	//set::iterator itr;
	//itr = s.begin();
	//for (int i = 0; i < 2; i++)
	//	itr = s.erase(itr);
	//for (itr = s.begin(); itr != s.end(); ++it)
	//{
	//	cout << *itr << " ";
	//}
	//cout << endl;
	s.clear();
	cout << s.size() << endl;


//查找元素
	set s{ 5,1,6,6,3,5,6 };
	set::iterator it;
	it = s.find(8);
	if(it != s.end())
	{
		cout << *it << endl;
	}
	else
	{
		cout << "not find it" << endl;
	}

	system("pause");
	return 0;
}


//自定义比较函数
struct mycomp
{
	bool operator()(const int& a, const int& b)
	{
		if (a != b)
			return a > b;
		else
			return a > b;
	}
};
int main()
{
	set s{ 2,3,4,5,6,5,1 };
	set::iterator it;
	for (it = s.begin(); it != s.end(); ++it)
		cout << *it << " ";
	cout << endl;
	system("pause");
	return 0;
}

set和multiset、unordered_set的区别
  multiset是不去重的,set是去重的;
  unordered_set是C++11中引入的新的容器,其内部不再采用红黑树实现,而是采用了hash表,加速了检索速度。
  set和map的内部实现是一样的,unordered_set和unordered_map的内部实现也是一样的。

map:

        map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据 处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。这里说下map内部数据的组织,map内部自建一颗红黑树(一 种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。

下面附上简单的代码及注释:

//map容器
//map是STL的一个关联容器,它提供一对一
//(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力
//map提供一对一的数据处理能力,内部是由红黑树实现的,具有自动排序能力,
//map内部的所以数据是有序的
int main()
{
//用insert插入pair数据
	map mapstudent;
	mapstudent.insert(pair(1, "s1"));
	mapstudent.insert(pair(2, "s2"));
	mapstudent.insert(pair(3, "s3"));
	mapstudent.insert(pair(4, "s4"));
	map::iterator it;
	for (it = mapstudent.begin(); it != mapstudent.end(); ++it)
	{
		cout << it->first << " " << it->second << endl;
	}


	//insert插入value_type数据
	map mapstudent;
	mapstudent.insert(map::value_type(1, "s1"));
	mapstudent.insert(map::value_type(2, "s2"));
	mapstudent.insert(map::value_type(3, "s3"));
	map::iterator it;
	for (it = mapstudent.begin(); it != mapstudent.end(); ++it)
	{
		cout << it->first << " " << it->second << endl;
	}

//用数组方式插入数据
	map mapstudent;
	mapstudent[1] = "s1";
	mapstudent[2] = "s2";
	mapstudent[10] = "s10";
	map::iterator it;
	for (it = mapstudent.begin(); it != mapstudent.end(); ++it)
	{
		cout << it->first << " " << it->second << endl;
	}
	int size = mapstudent.size();  //
	cout << mapstudent.size() << endl;

//数据的遍历
	map mapstudent;
	mapstudent.insert(pair(1, "s1"));
	mapstudent.insert(pair(2, "s2"));
	mapstudent.insert(pair(3, "s3"));
	mapstudent.insert(pair(4, "s4"));
	map::reverse_iterator it;
	for (it = mapstudent.rbegin(); it != mapstudent.rend(); it++)
	{
		cout << it->first << " " << it->second << endl;
	}

	//数据的查找
	map mapstudent;
	mapstudent.insert(pair(1, "s1"));
	mapstudent.insert(pair(2, "s2"));
	mapstudent.insert(pair(3, "s3"));
	mapstudent.insert(pair(4, "s4"));
	map::iterator it;
	it = mapstudent.find(3);
	if (it != mapstudent.end())
	{
		cout << "find:" << it->second << endl;
	}
	else
		cout << "not find" << endl;

	//map的判空
	//如果要删除1,用迭代器删除  
	map mapstudent;
	mapstudent.insert(pair(1, "s1"));
	mapstudent.insert(pair(2, "s2"));
	mapstudent.insert(pair(3, "s3"));
	mapstudent.insert(pair(4, "s4"));
	map::iterator iter;
	iter = mapstudent.find(1);
	mapstudent.erase(iter);
	//如果要删除1,用关键字删除  
	int n = mapstudent.erase(1);//如果删除了会返回1,否则返回0  
								//用迭代器,成片的删除  
								//一下代码把整个map清空  
	mapstudent.erase(mapstudent.begin(), mapstudent.end());
	//成片删除要注意的是,也是STL的特性,删除区间是一个前闭后开的集合  

	system("pause");
	return 0;
}

Set和map的区别?

    set和map的区别就在于键和值是否相同,set中将值作为键,支持STL的提供的一些交集、并集和差集等运算;map的键和值不同,每个键都有自己的值,键不能重复,但是值可以重复。multimap和multiset就在map和set的基础上,使他们的键可以重复,除此之外基本等同。

set是一种关联式容器,其特性如下:

  1. set以RBTree作为底层容器
  2. 所得元素的只有key没有value,value就是key
  3. 不允许出现键值重复
  4. 所有的元素都会被自动排序
  5. 不能通过迭代器来改变set的值,因为set的值就是键

map和set一样是关联式容器,它们的底层容器都是红黑树,区别就在于map的值不作为键,键和值是分开的。它的特性如下:

  1. map以RBTree作为底层容器
  2. 所有元素都是键+值存在
  3. 不允许键重复
  4. 所有元素是通过键进行自动排序的
  5. map的键是不能修改的,但是其键对应的值是可以修改的

其它相关(红黑树与哈希表)

红黑树:

红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:

  • 性质1. 节点是红色或黑色。
  • 性质2. 根节点是黑色。
  • 性质3 每个叶节点(NIL节点,空节点)是黑色的。
  • 性质4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
  • 性质5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

哈希表

   哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

  • 1、Hash主要用于信息安全领域中加密算法,它把一些不同长度的信息转化成杂乱的128位的编码,这些编码值叫做Hash值. 也可以说,Hash就是找到一种数据内容和数据存放地址之间的映射关系。
  • 2、查找:哈希表,又称为散列,是一种更加快捷的查找技术。我们之前的查找,都是这样一种思路:集合中拿出来一个元素,看看是否与我们要找的相等,如果不等,缩小范围,继续查找。而哈希表是完全另外一种思路:当我知道key值以后,我就可以直接计算出这个元素在集合中的位置,根本不需要一次又一次的查找!
  • 3、Hash表在海量数据处理中有着广泛应用。  

 

你可能感兴趣的:(数据/算法,C++)