STL——set multi_set map multi_map unordered_set unordered_map heap priority_queue(3)

最近做编程题发现关联容器忘得多,翻翻以前写的代码,mark一下,勉励自己

目录

基本概念

map  multi_map

unordered_set  unordered_map

具体成员函数API调用代码

priority_queue 

push_heap pop_heap sort_heap  

参考:



基本概念

map  multi_map

  • map是标准的关联式容器,一个map是一个键值对序列,即(key,value)对。它提供基于key的快速检索能力。
  • map中key值是唯一的。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。
  • map的具体实现采用红黑树变体的平衡二叉树的数据结构。在插入操作和删除操作上比vector快。
  • map可以直接存取key所对应的value,支持[]操作符,如map[key]=value。
  • multimap与map的区别:map支持唯一键值,每个键只能出现一次;而multimap中相同键可以出现多次。multimap不支持[]操作符。

unordered_set  unordered_map

无序容器   使用hash函数和==运算
桶管理:将具有相同hash值的元素保存在同一个桶中。无序容器的性能依赖于hash函数的性质和桶的大小和数量
成员函数和map set差不多,关于有序的函数没有,多了桶管理函数

具体成员函数API调用代码

#include<iostream>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<unordered_set>
#include<unordered_map>
#include<functional>

using namespace std;


//定义关联容器
void countre_init()
{
	vector<int>v = { 1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1 };
	set<int>s(v.begin(), v.end());//不允许重复
	multiset<int>multi_s(v.begin(), v.end());
	//列表初始化
	map < string, string >m = { {"zhangsan", "wangbadan"}, { "lisi","wangjiudan" }, { "zhangsan", "wangbadan" } };
	multimap < string, string >multi_m = { { "zhangsan", "wangbadan" },{ "lisi","wangjiudan" },{ "zhangsan", "wangbadan" } };

	cout << v.size() << " " << s.size() << " " << multi_s.size() << endl;
	cout << m.size() << " " << multi_m.size() << endl;
}
//使用关键字类型的比较函数 自定义<
bool compare(int a, int b)
{return a < b ?  false:true;}//从大到小

//仿函数::又叫函数对象,一种行为类似函数的对象。调用者可以向函数一样使用该对象。
//实现:用户只需要实现一种新的类型,在类中进行重载(),参数根据用户索要进行的操作选择匹配
class Greater//或struct
{
public:
	bool operator()(const string str1, const string str2)
	{
		return str1.size() < str2.size() ? true : false;
	}
};
void key_function()
{
	//set map 等有序集合 实现排序的时 默认使用<比较两个关键字
	//自定义的操作类型在尖括号里紧跟元素类型
	set<int, decltype(compare)*>s(compare);//必须指明指针类型  decltype推断函数类型
	map<int, int,decltype(compare)*>m(compare);
	for (int i = 0; i < 10; i++)
	{
		s.insert(i);
		m.insert(make_pair(i+5, i));
	}
	for (auto c : s)
		cout << c << " ";
	cout << endl;

	auto map_it = m.begin();
	while (map_it != m.end())
	{
		cout << map_it->first << " " << map_it->second << endl;
		map_it++;
	}

	//实现倒序  谓词  greater #include<functional>
	//set<int,less<int> >  setIntA;  //该容器是按升序方式排列元素。
	//set<int, greater<int>> setIntB;   //该容器是按降序方式排列元素。
	set<string, greater<string>>s2 = { "zhangsan","lisi","wangwu","maliu","luqi","wangba" };
	for (auto c : s2)
		cout << c << " " << endl;
	//实现倒序 仿函数
	set<string, Greater>s3 = { "zhangsan","lisi","wangwu","maliu","luqi","wangba" };
	for (auto c : s3)
		cout << c << " " << endl;
	
}

void pair_make()
{
	//pair类型 用于生成特定类型的模板,两个public成员first second  make_pair()函数 ==  !=等操作
	//key_type (关键字类型)  mapped_type(值类型,只适用于map)  value_type(对于set为键值类型,map为pair类型) 
	//每个pair的关键字key为const不可改变,但是value可以改变  set只有key值所以不可变
	//采用作用域访问

 	pair<string, int>author("zhangsan", 33);
	cout << author.first << author.second << endl;
	author.second = 44;//合法 author.first = "lisi"  违法
	set<int>s = { 1,2,3 };
	set<int>::iterator it = s.begin();
	cout << *it << endl;// *it = 2;//违法  只读
	pair<string, int>t = make_pair("zhangsan", 44);//make_pair()函数
	
	vector<pair<string, int>>v;
	vector<string>v2 = { "zhangsan","lisi","wangmazi" };
	for(int i = 0;i<10;i++)
		v.push_back(make_pair(v2[i%3], i + 30));
	for (auto c : v)
		cout << c.first << " " << c.second << endl;
}

//插入insert 删除erase
void insert_function()
{
	vector<int>v = { 1,2,3,4,5,6,7,4,6,78,2,5 };
	set<int>s;
	s.insert(v.begin(), v.end());
	s.insert(0);
	for (auto c : s)
		cout << c << " ";
	cout << endl;
	cout<<s.erase(5)<<endl;//erase(key)删除键值为key的元素,返回删除元素的个数,set01 multi 多个
	cout << *(s.erase(s.begin())) << endl;//删除迭代器所指的元素,返回下一个迭代器
	s.erase(++s.begin(), --s.end());//范围删除,+ - 不支持
	for (auto c : s)
		cout << c << " ";
	cout << endl;
	s.insert(v.begin() + 3, v.end() - 1);

	map<string, int>m;
	m.insert({ "zhangsan",22 });//最简单,常用花括号和make_pair()
	m.insert(make_pair("lisi", 33));
	m.insert(pair<string, int>("wangwu", 44));
	m.insert(map<string, int>::value_type("maliu", 55));
	//insert返回值w为pair(iterator,bool)iterator指向待插入元素的位置,bool表示插入是否成功,成功则true
    //对于map 和set返回pair 对于multimap和multiset插入总是成功,返回iterator
	auto ret1 = s.insert(0);
	if (ret1.second == false)
		cout << "插入0失败" << endl;
	auto ret2 = m.insert({ "zhangsan",22 });
	if (ret2.second == false)
		ret2.first->second += 11;
	cout << ret2.first->first << " " << ret2.first->second << endl;//ret2.first指向待插入(重复)迭代器
	//对于multi返回迭代器
	multimap<string, int>m2 = { {"zhangsan",22} };
   auto it = m2.insert({ "zhangsan", 33 });
   m2.insert({ "lisi",44 });
   cout << it->first << " " << it->second << endl;
   cout << m2.erase("lisi") << endl;//返回1个

   //map的下标操作 set 和multiset multimap不存在下表操作,不存在值或者值不唯一
   //[]先检查有没有,没有则创建,有则返回value_type 与迭代器不同,迭代器解引用返回pair类型
   map<string, int>m3;//一个空map
   m3["zhangsan"] = 44;//1)首先查找"zhangsan",没找到 2) 插入关键字zhangsan 值默认为0  3)将4赋值给zhangsan 
   m3.at("zhangsan") = 55;//先查找,没有则抛出异常out_of_ranage否则返回value_type

   //访问元素
   cout<<*(s.find(1))<<endl;//返回一个迭代器,找不到返回s.end();
   cout << s.count(2) << endl;//返回一个数,key=2的个数
   //只有有序容器中可用
   cout << *s.lower_bound(3) << endl;//返回第一个不小于3的迭代器
   cout << *s.upper_bound(3) << endl;//返回第一个大于3的迭代器
   //multiset 和 multimap中查找,相同的key保存在相邻的位置
   cout << endl << endl << endl;
   auto it3 = m2.find("zhangsan");
   int count = m2.count("zhangsan");
   while (count)
   {
	   cout << it3->first << " " << it3->second << endl;
	   count--;
	   it3++;
   }
   //upper_bound("zhangsan")找到则返回zhangsan下一个位置(尾后),未找到则返回一个可以插入zhangsan的位置
   //不影响序列有序,可能zhangsan最大,找到end==m2.end() 也可能没找到  同时最大end == m2.end(),所以
   //不能根据其返回值判断是否找到,但是返回一个范围,可以输出

   for (auto beg = m2.lower_bound("zhangsan"), end = m2.upper_bound("zhangsan"); beg != end; beg++)
	   cout << beg->first << " " << beg->second << endl;

   //equal_ranage找到则返回pair(iterator1,iterator2);iterator1指向第一个,iterator2指向最后一个的尾后
   //如果没有找到则同时指向一个可以插入的位置
   for(auto pos = m2.equal_range("zhangsan"); pos.first!= pos.second; pos.first++)
	  cout << pos.first->first << " " << pos.first->second << endl;
}

//无序容器   使用hash函数和==运算
// 桶管理:将具有相同hash值的元素保存在同一个桶中。无序容器的性能依赖于hash函数的性质和桶的大小和数量
//成员函数和map set差不多,关于有序的函数没有,多了桶管理函数

void unordered_container()
{
	unordered_map<string, int>un_m = { {"ccc",3}, {"aaa",1},{"bbb",2 } };
	un_m.insert({ "ddd",4 });
	for (auto pos: un_m)
	{
		cout << pos.first << " " << pos.second << endl;
	}
	un_m.erase("ccc");
	for (auto pos : un_m)
	{
		cout << pos.first << " " << pos.second << endl;
	}
	auto it = un_m.find("aaa");
	cout << it->first << " " << it->second << endl;
	cout << un_m.count("ddd") << endl;

	//桶管理函数:允许我们查看桶的状态,必要时进行重组
	cout<<un_m.bucket_count()<<endl;//正在使用的桶数量
	cout << un_m.max_bucket_count()<<endl;//容器最多能容纳的桶的数量
	cout << un_m.bucket_size(2) << endl;//第2个桶有几个元素
	cout << un_m.bucket("ddd") << endl;//关键字为"ddd"在哪个桶里
	cout << un_m.load_factor() << endl;//平均每个桶有几个元素


}


int main()
{
	
	countre_init();
	key_function();
	pair_make();
	insert_function();
	unordered_container();
	//调用函数对象,创建一个函数对象,调用它
	Greater a;
	cout<<a("zhangsan", "lisi")<<endl;
	return 0;
}

 


priority_queue:

    //使用方法 priority(Type,Conteiner,Function)
    //std::priority_queue<T, std::vector<T>, greater<T>> pq;
    //不加后面两个参数的话默认为 container 默认为vector function默认为less  大顶堆 
    //小顶堆 基本类型 priority_queue<int, vector<int>, greater<int> >q3;
    //自定义型 则重载< 
    //函数greater在<functional>

 push_heap pop_heap sort_heap

    将[begin, end)范围进行堆排序,默认使用less<int>, 即最大元素放在第一个。
    make_heap(v.begin(), v.end());

    //将begin移动到end的前部,同时将剩下的元素堆排序为一个新的heap
    //配合vector的pop_back进行出堆操作
    pop_heap(v.begin(), v.end());  v.pop_back();

    //刚插入的(尾部)元素做堆排序
    v.push_back(100);  push_heap(v.begin(), v.end());

   //将一个堆做排序,最终成为一个有序的系列,可以看到sort_heap时,必须先是一个堆
    //(两个特性:1、最大元素在第一个 2、添加或者删除元素以对数时间),因此必须先做一次make_heap.
    sort_heap(v.begin(), v.end());

push_heap pop_heap sort_heap的基本操作:

void heap_opt()
{
	//include<algorithm> "functional"
	int myints[] = { 10,20,30,5,15 };
	vector<int> v(myints, myints + 5);
	vector<int>::iterator it;

	//将[begin, end)范围进行堆排序,默认使用less<int>, 即最大元素放在第一个。
	make_heap(v.begin(), v.end());
	cout << "初始堆堆顶 : " << v.front() << endl;

	//将begin移动到end的前部,同时将剩下的元素堆排序为一个新的heap
	//配合vector的pop_back进行出堆操作
	pop_heap(v.begin(), v.end()); v.pop_back();
	cout << "max heap after pop : " << v.front() << endl;

	//刚插入的(尾部)元素做堆排序
	v.push_back(100); push_heap(v.begin(), v.end());
	cout << "max heap after push: " << v.front() << endl;

	//将一个堆做排序,最终成为一个有序的系列,可以看到sort_heap时,必须先是一个堆
	//(两个特性:1、最大元素在第一个 2、添加或者删除元素以对数时间),因此必须先做一次make_heap.
	sort_heap(v.begin(), v.end());

	cout << "最终堆顺序:";
	for (unsigned i = 0; i<v.size(); i++) cout << " " << v[i];
	cout << endl;
}

priority_queue的基本操作:

void priority_queue_opt()
{
	//使用方法 priority(Type,Conteiner,Function)
	//std::priority_queue<T, std::vector<T>, greater<T>> pq;
	//不加后面两个参数的话默认为 container 默认为vector function默认为less  大顶堆 
	//小顶堆 基本类型 priority_queue<int, vector<int>, greater<int> >q3;
	//自定义型 则重载< 
	//函数greater在<functional>
	priority_queue<int> q1;
	//默认是最大值优先队列 q1等价于q2
	priority_queue<int, vector<int>, less<int>>q2;
	priority_queue<int, vector<int>, greater<int> >q3;

	q2.push(1);
	q2.push(3);
	q2.push(4);
	q2.push(6);
	cout << "q2.size" << q2.size() << endl;
	while (!q2.empty())
	{
		cout << q2.top() << ' ';
		q2.pop();
	}
	cout << endl;
	q3.push(6);
	q3.push(3);
	q3.push(2);
	q3.push(1);
	while (!q3.empty())
	{
		cout << q3.top() << ' ';
		q3.pop();
	}
	cout << endl;

}

利用大顶堆小顶堆进行取中位数:

class MidNum {
public:
	void Insert(int num)
	{
		if (((min.size() + max.size()) & 1) == 0)//目前总共偶数个数字
		{
			if (max.size()>0 && num<max[0])//偶数个应该放在最小堆,但是数字比大顶堆最大值小
			{
				//vector.push_back  push_back() 数字进堆
				//调整,先进大顶堆,将大顶堆最大放入最小堆保持元素差1
				max.push_back(num);
				//将front移动到end的前部,同时将剩下的元素重新构造成(堆排序)一个新的heap
				push_heap(max.begin(), max.end(), less<int>());

				num = max[0];

				//pop_heap  vector.pop_back数字出堆
				//将[first, last)范围进行堆排序,默认使用less<int>, 即最大元素放在第一个。
				pop_heap(max.begin(), max.end(), less<int>());
				max.pop_back();
			}
			min.push_back(num);
			push_heap(min.begin(), min.end(), greater<int>());
		}
		else
		{
			if (min.size()>0 && min[0]<num)//本来要插入大顶堆,结果num小顶堆最小值小
			{
				min.push_back(num);
				push_heap(min.begin(), min.end(), greater<int>());

				num = min[0];

				pop_heap(min.begin(), min.end(), greater<int>());
				min.pop_back();
			}
			max.push_back(num);
			push_heap(max.begin(), max.end(), less<int>());
		}
	}

main测试函数

int main()
{

	srand(time(0));
	heap_opt();
	priority_queue_opt();
	MidNum m;
	for (int i = 1; i < 10; ++i)
		m.Insert(rand() % 100);
	cout << m.GetMedian();
	return 0;
}

结果:

 

参考:

primer

C++Reference

剑指offer 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值