C++(map和set)

set

set是key模型,属于关联式容器,并非序列式容器,数据之间有非常大的关联关系,所以不是像序列式容器一样头尾随便插,所以不用push这个概念了,而是采用insert按照关联规则进行插入。

set的功能不是单纯的排序,还具有去重的功能。

int main()
{
	set<int> s1;
	s1.insert(1);
	s1.insert(3);
	s1.insert(2);
	s1.insert(7);
	s1.insert(2);
	s1.insert(6);
	s1.insert(1);
	s1.insert(3);
	s1.insert(8);
	s1.insert(5);
	s1.insert(0);
	set<int>::iterator it = s1.begin();
	while (it != s1.end())
	{
		//*it+=1;//set的底层式平衡搜索二叉树,是不允许修改key的,因为这样会破坏搜索二叉树的结构
		cout << *it << " ";
		it++;
	}
	//判断x在不在set容器里面
	int x;
	while (cin >> x)
	{
		//方法一
		/*	auto ret = s1.find(x);
			if (ret != s1.end())
			{
				cout << "在" << endl;
			}
			else
			{
				cout << "不在" << endl;
			}*/
		//方法二
		if (s1.count(x))//count是用来返回x值在容器当中的个数,但是再set模型中显得感觉有些鸡肋。其实count的作用再multiset容器中才更适用。
		{
			cout << "在" << endl;
		}
		else
		{
			cout << "不在" << endl;
		}
	}
	return 0;
}

multiset

插入的时候允许键值冗余,所以式单纯的排序,不报错去重。

int main()
{
	multiset<int> s1;
	s1.insert(1);
	s1.insert(3);
	s1.insert(2);
	s1.insert(7);
	s1.insert(2);
	s1.insert(6);
	s1.insert(1);
	s1.insert(3);
	s1.insert(8);
	s1.insert(5);
	s1.insert(0);
	multiset<int>::iterator it = s1.begin();
	while (it != s1.end())
	{
		//*it+=1;//set的底层式平衡搜索二叉树,是不允许修改key的,因为这样会破坏搜索二叉树的结构
		cout << *it << " ";
		it++;
	}
}

如何实现这种冗余插入呢?其实相同的值也一样插入,再该值的左边或者右边都可以。

int main()
{
	multiset<int> s1;
	s1.insert(1);
	s1.insert(3);
	s1.insert(2);
	s1.insert(7);
	s1.insert(1);
	s1.insert(6);
	s1.insert(1);
	s1.insert(3);
	s1.insert(8);
	s1.insert(1);
	s1.insert(8);
	s1.insert(8);
	s1.insert(0);
	set<int>::iterator it = s1.begin();
	//当有多个key时,找中序排列的第一个key,比如说按照搜索二叉树的规则来进行比较大小找到第一个key,如果有多个相同的key并不是直接选择这个key,而是继续向左子树找最左边的key,所以也可以理解为找中序的第一个key
	//下面也可以印证这个说法
	auto ret = s1.find(1);
	while (ret != s1.end() && *ret == 1)
	{
		cout << *ret << " ";
		ret++;
	}
}

map

map时key/value模型 

int main()
{
	map<string, string> dict;
	dict.insert(pair<string,string>("left", "左"));//传统的写法时喜欢插入pair的匿名构造函数
	dict.insert(make_pair("front", "前"));//但是我们更喜欢用make_pair模板函数,其实先也是调用pair的匿名构造来return,但是优势是可以不用传模板参数,函数自己来推导
	dict.insert(make_pair("right", "右"));
	dict.insert(make_pair("behind", "后"));
	dict.insert(make_pair("behind", "后面"));//该行代码插入失败,因为搜索二叉树中value不会参与搜索的规则,只管key值,key值已经有了所以插入失败。
	dict["string"] = "(字符串)"; //修改,该行代码可以成功修改string对应的value
    dict["sounth"];			// 插入,而south的value是没有办法显示给的,只能给valud的默认构造也就是string的默认构造就是一个空串
	dict["north"] = "右边"; // 插入并且可以通过这种方式给value
    cout << dict["string"] << endl; // 对于已存在map里面的key是查找对应的value
	cout << dict["west"] << endl; // 对于不存在在map里面的key返回空串
	auto dit = dict.begin();
	while (dit != dict.end())
	{
		cout << (*dit).first << ":" << (*dit).second << endl;//不能写成cout<<*dit<<" ",因为*dit返回的是一个结构pair,而pair并不支持流插入
		cout << dit->first << ":" << dit->second << endl;//上面一行时通过c++运算符重载*来解引用数据,而c++也重载了符号->。dic调用operator时返回的时数据的地址pair<stinr,string>*,由此可以编译器在这里省略了一个箭头,也可以理解成优化掉了。

		++dit;
	}
	cout << endl;
}

 

 

map的[ ]运算符重载 

int main()
{
	string arr[] = { "西瓜", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉", "梨" };
	map<string, int> countMap;
	//统计次数的传统写法
	//for (auto& e : arr)//加上引用,避免走string的深拷贝
	//{
	//	auto ret = countMap.find(e);
	//	if (ret == countMap.end())
	//	{
	//		countMap.insert(make_pair(e, 1));
	//	}
	//	else
	//	{
	//		ret->second++;
	//	}
	//}
	//现代的写法:一行代码统计次数
	for (auto& e : arr)
	{
		countMap[e]++;//能这样写的原因再下面,原因在下面。[]的功能:
        //1、插入,e不存的话我直接插入,只是mapped_type()采用的是默认构造
        //2、返回值mapped_type类型变量的引用,你可以用来查找也可以进行充型赋值修改数据
	}

	for (auto& kv : countMap)
	{
		cout << kv.first << ":" << kv.second << endl;
	}
	return 0;
}
//
mapped_type& operator[] (const key_type& k)
{
	return (*((this->insert(make_pair(k, mapped_type()))).first)).second
}
//翻译一下
mapped_type& operator[] (const key_type& k)
{
	pair<iterator, bool> ret = insert(make_pair(k, mapped_type()));z//insert的返回值是一个pair结构体,其中的第二个参数second是bool值,表述插入是否成功,插入成功就是true否则就是false。第一个参数是一个迭代器,指向新插入的元素或者和key相等的元素。在这里插入的元素是(k,mapped_type()),而mapped_type在这里是int类型,用来统计水果的个数,所以这里调用的mapped_type()就是int类型的默认构造,也就是0。 
	return ret.first->second;//ret是一个pair<iterator, bool>,ret.first就是一个迭代器,迭代器指向插入的元素的位置,它的second就是统计的个数
    //当水果第一次出现的时候,成功插入(“水果”,0),返回当前水果再map中的位置iterator的second也就是次数0。当水果已经存在与map当中的时候,就插入失败,返回当前已存在map当中水果的位置iterator的second也就是水果之前出现的次数。
}

multimap

允许键值冗余,但是没有了[ ]运算符重载。因为现在key和value的关系是一对多了,而[ ]运算符重载的核心功能是查找key对应的value,找到了可以对改值进行获取甚至修改。

int main()
{
	multimap<string, string> mdict;
	mdict.insert(make_pair("sort", "排序"));
	mdict.insert(make_pair("string", "字符串"));
	mdict.insert(make_pair("count", "计数"));
	mdict.insert(make_pair("string", "(字符串)")); // 插入成功
	mdict.insert(make_pair("string", "字符串"));
	for (auto& kv : mdict)
	{
		cout << kv.first << ":" << kv.second << endl;
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值