C++STL库之map

关于仿函数

在这里插入图片描述
在这里插入图片描述

//C++不能重载的运算符sizeof、 ::、 ? :、 .、 *、
class Add
{
public:
	int operator()(int a, int b)const
	{
		return a + b;
	}
};
//函数对象,仿函数,函子
int main()
{
	Add add;

	int x = 10, y = 20, z = 30; 
	z = add(x, y);  //C++11
	z = add.operator()(x, y);  //重载了括号调用

	cout << z << endl;
}
template<class _Ty>
class Add
{
public:
	_Ty operator()(const _Ty& a, const _Ty& b)const
	{
		return a + b;
	}
};

int main()
{
	Add<int>iadd;
	Add<double>dadd;

	int x = 10, y = 20, z = 0;
	z = Add<int>()(x, y);   //Add<int>():类型名+()  创建了不具名对象(右值)
	z = Add<int>().operator()(x, y);  //仿函数
	return 0;
}
int main()
{
	std::vector<int>ar = { 1,4,5,6,7,8,3,2,9,0 };
	std::sort(ar.begin(),ar.end(),std::less<int>());
	for (auto& x : ar)
	{
		cout << x << " ";
	}
	cout << endl;

	std::sort(ar.begin(), ar.end(), std::greater<int>()); //仿函数,从大到小排序

	for (auto& x : ar)
	{
		cout << x << " ";
	}
	cout << endl;
}
struct my_less
{
	bool operator()(const _Ty& a, const _Ty& b)const
	{
		return a < b;
	}
};
template<class _Ty>
struct my_greater
{
	bool operator()(const _Ty& a, const _Ty& b)const
	{
		return a > b;
	}
};

template<class _BI,class _Fn>
void my_sort(_BI _first, _BI _last,_Fn fn)
{
	cout << typeid(_BI).name() << endl;
	cout << typeid(_Fn).name()<< endl;
	for (_BI i = _first;i != _last; ++i)  //插入排序
	{
		_BI k = i;
		for (_BI j = i+1; j!=_last; ++j)
		{
			if (*k > *j)
			{
				k = j;
			}
		}
		if (k!= i)
		{
			std::swap(*k, *i);
		}
	}
}

int main()
{
	std::vector<int>ar = { 1,4,5,6,7,8,3,2,9,0 };
	my_sort(ar.begin(), ar.end(),my_less<int>());
	//std::sort(ar.begin(),ar.end(),std::less<int>());
	for (auto& x : ar)
	{
		cout << x << " ";
	}
	cout << endl;

	my_sort(ar.begin(), ar.end(),my_greater<int>()); //仿函数,从大到小排序

	for (auto& x : ar)
	{
		cout << x << " ";
	}
	cout << endl;
}

运行结果:
在这里插入图片描述

stack

  • 关于栈的返回值:以引用形式返回,以值的形式接受(不能以引用接受,会产生失效引用,或者会修改栈顶的值)
  • 默认情况栈的底层实现,双端对列实现
class PtrInt
{
	int* ptr;
public:
	PtrInt(int x = 0) :ptr(new int(x))
	{
		cout << "Create PtrInt:" << endl;
	}
	PtrInt(const PtrInt& pt) :ptr(new int())
	{
		if (pt.ptr != nullptr)
		{
			*ptr = *pt.ptr;
		}
		cout << "Copy Create:" << endl;
	}
	PtrInt& operator=(const PtrInt& pt)
	{
		if (this != &pt)
		{
			delete ptr;
			ptr = new int();
			if (pt.ptr != nullptr)
			{
				*ptr = *pt.ptr;
			}
			cout << "operator=()" << endl;
		}
		return *this;
	}
	PtrInt(PtrInt&& pt) :ptr(pt.ptr)
	{
		pt.ptr = nullptr;
		cout << "move create" << endl;
	}
	PtrInt& operator=(PtrInt&& pt)
	{
		if (this != &pt)
		{
			delete ptr;
			ptr = pt.ptr;
			pt.ptr = nullptr;
		}
		cout << "move operator=()" << endl;
		return *this;
	}
	~PtrInt()
	{
		delete ptr;
		ptr = nullptr;
		cout << "Destory PtrInt" << endl;
	}
	
	void SetValue(int x)
	{
		if (ptr != nullptr)
		{
			*ptr = x;
		}
		else
		{
			ptr = new int(x);
		}
	}
	int GetValue()const
	{
		if (ptr != nullptr)
		{
			return *ptr;
		}
		else
		{
			return -1;
		}
	}
	void Print()const
	{
		if (ptr != nullptr)
		{
			cout << *ptr << endl;
		}
	}
};

int main()
{
	stack<PtrInt>ist;
	ist.push(PtrInt(10));
	ist.push(PtrInt(20));
	ist.push(PtrInt(30));

	stack<PtrInt, std::list<PtrInt>>list; //链栈
	stack<PtrInt, std::vector<PtrInt>>sqst; //顺序栈

	PtrInt &val = ist.top(); //返回值为引用,但是以引用接受,最好以值接受,以引用返回
	//为什么以引用的形式返回,因为以值返回会产生将亡值对象
	
	val.Print();
	ist.pop();
	//val.Print();  //栈顶已经析构掉了,引用失效
	
	return 0;
}

deque(双端对列)

既可以在尾部插入,也可以在头部插入(栈没有迭代器,不能进行迭代)

int main()
{
	deque<int>deq;

	deq.push_back(12);
	deq.push_back(23);
	
	deq.push_front(100);
	deq.push_front(120);

	for (auto& x : deq)
	{
		cout << x << endl;
	}
}

queue

队列的底层实现可以为双端队列,或者list,但是不允许为vector,因为vector没有pop_front的方法

int main()
{
	queue<int, deque<int>>qu;
	queue<int, list<int>>lqu;

	lqu.push(12);
	lqu.push(23);

	int x = lqu.front();  //不要拿引用接受
	lqu.pop();
	cout << x << endl;
	//queue<int, std::vector<int>>vqu;  //不允许拿vector构建队列
}

priority_queue

int main()
{
	std::priority_queue<int,std::vector<int>,greater<int>>qu; //从小到大取元素(小堆序),默认大堆序
	qu.push(12);
	qu.push(23);
	qu.push(8);
	qu.push(34);
	qu.push(56);
	qu.push(3);

	while (!qu.empty())
	{
		int val = qu.top();
		qu.pop();
		cout << val << endl;
	}
}

map(重点)

底层实现(红黑树):关联容器。


template<class T1,class T2>
struct my_pair
{
	using first_type = T1;  //重命名
	using second_type = T2;

	first_type first;
	second_type second;
};

my_pair<int, string>myp{ 12, "hhh" };

template<class _Key,class _Val>
class my_map
{
	using value_type = my_pair<_Key, _Val>;
	struct _rbnode
	{
		value_type data;  //data.first=>Key data.second=>Value
	};
};

int main()
{
	//std::map<int, std::string>ismap;
	//       key       value

	//value_type由pair进行重命名
	std::map<std::string, int>simap;
	//关键码不允许重复
	simap.insert(std::map<std::string, int>::value_type("hhh",12));
	simap.insert(std::map<std::string, int>::value_type("ppp", 34));
	simap.insert(std::map<std::string, int>::value_type("rrr", 56));
	simap.insert(std::map<std::string, int>::value_type("www", 23));
	simap.insert(std::map<std::string, int>::value_type("aaa", 78));
	simap.insert(std::map<std::string, int>::value_type("bbb", 45));

	for (auto& x:simap)
	{
		cout << x.first << " " << x.second << endl;
	}
}

在这里插入图片描述

int main()
{
	using SIMP = std::map<std::string, int>;
	using ValType = std::map<std::string, int>::value_type;
	SIMP simap;
	simap.insert(ValType("hhh", 12));
	simap.insert(ValType("www", 23));
	simap.insert(ValType("rrr", 34));
	simap.insert(ValType("ttt", 21));
	simap.insert(ValType("uuu", 6));
	simap.insert(ValType("kkk", 10));


	for (auto& x : simap)
	{
		cout << x.first << " " << x.second << endl;
	}

	std::map<string, int, greater<string>>::iterator ita = simap.begin();
	auto it = simap.begin();  //可以直接用auto推导
	for (; it != simap.end(); ++it)
	{
		cout << it->first << " " << it->second << endl;
	}
}

at与operator[] 的区别:
at:通过关键码查询值,如果找不到,直接报错
operator[]:通过关键码查询值,如果找不到,则在红黑树中构建一个元素,并且将value的值赋值0
在这里插入图片描述
用map统计文件中单词的个数,并进行排序(状态机)

#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<deque>
#include<queue>
#include<stack>
#include<list>
#include<map>
using namespace std;

#define BEGIN 0
#define IN_WORD 1
#define OUT_WORD 2

int main()
{
	FILE* fp = fopen("day0513.cpp", "r");
	if (nullptr == fp)exit(EXIT_FAILURE);
	int const len = 256;
	char str[len] = {};
	int tag = BEGIN;
	int posi;
	std::map<string, int>simap;
	while (!feof(fp))
	{
		fgets(str, 256, fp);
		for (int i = 0; str[i] != '\0' && i < len; ++i)
		{
			switch (tag)
			{
			case BEGIN:
				if (isalpha(str[i]))
				{
					posi = i;
					tag = IN_WORD;
				}
				else
				{
					tag = OUT_WORD;
				}
				break;
			case IN_WORD:
				if (!isalpha(str[i]))
				{
					std::string word(&str[posi], i - posi); //i-posi分离出每个单词
					//cout << word << endl;
					simap[word] += 1;
					tag = OUT_WORD;
				}
				break;
			case OUT_WORD:
				if (isalpha(str[i]))
				{
					posi = i;
					tag = IN_WORD;
				}
				break;
			}
		}
	}
	fclose(fp);
	fp = nullptr;
	/*for (auto& x : simap)
	{
		cout << x.first << " " << x.second << endl;
	}*/
	std::multimap<int,string>ismap;
	for (auto& x :simap)
	{
		ismap.insert(std::multimap<int, string>::value_type(x.second, x.first));
	}

	for (auto& x : ismap)
	{
		cout << x.first << " " << x.second << endl;
	}
	return 0;
}

关于map的底层
在这里插入图片描述

为什么打印出来的数据为:12,23,34,45,56,67 ?
因为底层为中序遍历

unordered_map(底层哈希链表):与map的区别是在于关键码是否有序

map的插入:

int main()
{
	std::map<int ,string>age_namemap;
	int age;
	string name;
	while(cin>>age>>name,age>=16||name!="end")
	{
		age_namemap[age]=name;
		age_namemap.insert(std::map<int,string>::value_type(age,name));
		age_namemap.insert(pair<const int,string>(age,name));
		//age_namemap.insert(age,name);//error
	}
}

多重map:允许关键码重复。

find
在map中进行查找,找到则返回该关键码迭代器,未找到则返回simap.end()

int main()
{
	std::map<string,int>simap;
	simap["aaa"]=20;
	simap["bbb"]=21;
	simap["ccc"]=22;
	
	std::map<string,int>::iterator it=simap.find("aaa");
	//std::map<string,int>::iterator it=simap.find("nnn");
	if(it!=simap.end())
	{
		cout<<it->first<<" "<<it->second<<endl;
	}
	else
	{
		cout<<"no key"<<endl;
	}
	return 0;
}

equal_range
在这里插入图片描述

  • 返回容器中所有拥有给定关键元素的范围
  • 范围以第二个迭代器定义
  • 一个指向首个不小于key的元素
  • 另一个指向首个大于key的元素
  • 首个迭代器可以换用lower_bound()获得
  • 而第二个迭代器可以换用upper_bound()获得
int main()
{
	std::map<int ,std::string>ismap;
	ismap[12]="hhh";
	ismap[34]="ttt";
	ismap[23]="qqq";
	ismap[67]="zzz";
	ismap[45]="ddd";
	ismap[56]="aaa";
	auto it=ismap.equal_range(45);
	auto Lt=ismap.lower_bound(45);
	auto Rt=ismap.upper_bound(45);
	
	auto p=ismap.begin();
	for(;p!=ismap.begin();++p)
	{
		cout<<p->first<<endl;
	}
}

在这里插入图片描述

在这里插入图片描述

multimap多重map(底层红黑树)

int main()
{
	std::multimap<int,std::string>ismap;
	ismap.insert(std::multimap<int,std::string>::value_type(18,"aaa"));
	ismap.insert(std::multimap<int,std::string>::value_type(20,"bbb"));
	ismap.insert(std::multimap<int,std::string>::value_type(18,"ccc"));
	ismap.insert(std::multimap<int,std::string>::value_type(21,"ddd"));
	ismap.insert(std::multimap<int,std::string>::value_type(34,"eee"));
	ismap.insert(std::multimap<int,std::string>::value_type(23,"fff"));
	ismap.insert(std::multimap<int,std::string>::value_type(23,"ggg"));
	ismap.insert(std::multimap<int,std::string>::value_type(22,"hhh"));
	ismap.insert(std::multimap<int,std::string>::value_type(26,"mmm"));

	auto it=ismap.equal_range(18);
	for(auto p=it.first;p!=it.second;++p)
	{
		cout<<p->first<<"---->"<<p->second<<endl;
	}
}

在这里插入图片描述

set(去重)

set:底层也是红黑树实现的
set中的元素排好序了
set容器中没有重复的元素

insert
在这里插入图片描述


int main()
{
	std::set<int>iset;
	for (int i = 0; i < 100; ++i)
	{
		auto it = iset.insert(rand() % 100);
		if (it.second)
		{
			cout << "insert 成功" << endl;
		}
		else
		{
			cout << "已经有重复值" << *it.first <<endl;
		}
	}
	std::set<int>::iterator it = iset.begin();
	for (; it != iset.end(); ++it)
	{
		cout << *it << endl;
	}
}

map与unordered_map的区别

int main()
{
	std::map<int, std::string>ismap;
	std::unordered_map<int, std::string>isunmap;

	ismap[12] = "hhh";
	ismap[34] = "ttt";
	ismap[23] = "qqq";
	ismap[67] = "zzz";
	ismap[45] = "ddd";
	ismap[56] = "aaa";

	isunmap[12] = "hhh";
	isunmap[34] = "ttt";
	isunmap[23] = "qqq";
	isunmap[67] = "zzz";
	isunmap[45] = "ddd";
	isunmap[56] = "aaa";
	cout << "map" << endl;
	for (auto& x : ismap)
	{
		cout << x.first << " " << x.second << endl;
	}
	cout << "------------------" << endl;
	for (auto& x : isunmap)
	{
		cout << x.first << " " << x.second << endl;
	}
}

在这里插入图片描述
无序map的底层是哈希表
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淡蓝色的经典

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值