c/c++常见容器总结

之前练算法很狂热的时候,由于觉得查到的一些容器的总结内容良莠不齐,遂总结了一下算法比赛中可能会用到的一些容器,但是一些不太常见的用法。

  • 注释都在代码里,也懒得重新写了,直接看代码吧,非常地干货
  • 代码可以直接在编译器里跑,便于测试
//几种常见容器有用但不常见操作      
#include<iostream>
#include<string>
#include<vector>
#include<deque>
#include<stack>
#include<queue>
#include<priority_queue>
#include<list>
#include<set>
#include<unordered_set>
#include<multiset>
#include<map>
#include<unordered_map>
#include<multimap>
using namespace std;
const int pos=0;
const size_N=3;
void StringTest()
{
//快速初始化 
	string str(10,'c'); //10个c
//迭代器初始化实现str的逆转 
	string rstr(str.rbegin(),str.rend()); 
//读取一行(包括空格)到string 
	getline(cin,str);
//字串操作 
	str.substr(pos,size_n);	//pos为字串开始位置(<0时表示从倒数第几个字符开始)
		//size_n为字串长度 	 //返回值也为string类型 
	str.substr(pos); //默认从pos到末尾 						
//查找字串 
	str.find("substr",pos); //从pos开始往后查找第一次出现"substr"的位置
	str.rfind("substr",pos); //从pos位置开始倒着查 
		//查不到的时候返回值为str.npos(其大小随实现改变,有的实现是-1,但这里不是)
		//一般用if(str.find(sstr,pos)==str.nops)来处理未找到
//string类型和其他类型之间的转换 
	int a=123456;
	str=to_string(a);	//将数字值转换为string
	stoi(str);	 
	string::size_type sz;
	stoi(str,&sz,2); //从头开始将能转为数字的字符串转换,并将结束位置传到sz 
	stoi(str,0,2);  //从头开始的字串转为10进制数字,第三个参数是将字符串看作几进制 
		//返回类型看尾巴是什么,还有stol(l),stoul(ul),stoll(ll),stof(float)
		//stod(double),stold(long double),其中浮点型无第三个参数几进制 
//字符串中间插入字符
	str.insert(pos,size_n,'c');	//在pos处插入size_n个'c' 
	str.insert(pos,"sstr",pos,size_n); //前两个参数同上,后两个是限定sstr的参数
		//插入从sstr的pos位置开始的size_n长度的字串
//删除
	str.erase(pos);	//删除pos到末尾 
	str.erase(pos,size_n); //删除pos开始的大小为size_n字串
}

void VectorTest()
{
//几种特殊初始化
	vector<int> v1={1,2,3};	//列表初始化
	int a[]={1,2,3};
	vector<int> va(a,a+3);	//数组初始化 
	vector<int> v2(10,1);	//10个1 
	vector<int> v3(10);	  //大内存要先开辟空空间,否则超过预留的空间将产生很多复制的操作 
	vector<int> v4[10];		//相当于二维数组 
	vector<vector<int>> v5;	//优于上面的二维数组 
//几种常用函数
	v1.emplace_back(1);	//尾插,也可以用push_back(),但前者效率更高 
	v1.pop_back();	//尾删
	auto it=v1.begin();	//正向迭代器,指向第一个元素,止于v1.end();
	auto rit=v1.rbegin(); //反向迭代器,指向最后一个元素,rit++从后往前遍历止于v1.rend(); 
	v1.emplace(it,3);	//迭代器指向位置插入也可以用emplace(v1.begin()+index,3);
		//相当于insert但是要高效于insert; 
	v1.erase(it);	//删除迭代器位置,也可以erase(v1.begin()+index);
		//迭代器指向位置不变,后面元素前移,于是删除后迭代器指向了下一个元素
	v1.erase(itb,ite);  //删除两个迭代器之间的元素	 
	v1.reserve(size_n); //非初始化时为容器开辟指定空间
//比较
	v1==v2;
	v1!=v2;
	v1>v2;	//字典序方式比较两个容器的内容 
}

void dequeTest()	//双向队列容器 
{
//类似于vector,首插和首删操作要优于vector
//一般情况下vector更优,deque仅仅优先选择于大量的首或尾删除操作.
//如果你打算用insert或者有pop_front()的需要,使用deque.
//比vector多的函数
	deque<int> d;
	d.emplace_front(1);
	d.pop_front();
}

void StackTest() //栈:先进后出 
{
//初始化
	stack<int> s;
//基操
	s.emplace(1); //等价于push(),入栈(尾插)
	s.top();	//获取栈顶元素其实也就是尾元素
	s.pop();	//移除栈顶元素(尾删) 
}

void QueueTest() //队列:先进先出
{
//初始化
	queue<int> q;	//默认应该是deque实现反正不是vector(vector首删比较麻烦) 
	queue<int,list<int>> q1;	//用list实现的queue
	queue<int,deque<int>> q2;	//用deque实现的queue
//基本操作
	q.emplace(1); //等价于push(),尾插
	q.front();	//获取头元素
	q.back();	//获取尾元素,没想到也能得到尾元素吧,"先进先出"只限制插入和删除 
	q.pop(); //首删
}

//自定义比较函数 
struct zdy{
	int x;
	bool operator<(const zdy&rhs)const{
		return x<rhs.x;	//大顶堆 
	}
};
//重写仿函数
struct cmp{
	bool operator()(zdy&a,zdy&b){
		return a.x<b.x;	//大顶堆 
	}
}; 
void Priority_queueTest()	//优先队列,具有队列的性质,但内部实现是个堆 
{ 
//可以做到高效获得优先级最高的元素,队首总是自动调节为优先级最高的元素
//基本类型(自带优先级比较函数)初始化 
	priority_queue<int> pq;	//默认为大顶堆
	priority_queue<int,vector<int>,greater<int>> pq1; //这样可以获得小顶堆
//对于自定义类型,需自己定义比较函数,或者重写仿函数(见上) 
	priority_queue<zdy> pq2;
	priority_queue<zdy,vector<zdy>,cmp> pq3;
//基操
	p.top();	//获取队头元素也就是优先级最高的那个元素
	p.emplace();	//等价于push(),插入元素并被排序到合适位置
	p.pop();	//删除队头元素 
}

void ListTest()	//双向链表 
{ //底层就是链表的实现 
//与向量(vectors)相比,它允许快速的插入和删除,但是随机访问却比较慢.
//初始化
	list<int> l;	//这样添加int型存的是复制到链表内的数据,并不是地址
	list<int*> l1;	//这样就是会存的已有变量的地址
		//小类型建议直接存数据,因为和地址大小差不多,但是大类型可以存地址节省内存
//访问
	l.front();	//返回第一个元素
	l.back();	//返回第一个元素
//迭代器
	l.begin();	//指向第一个元素 
	l.end();	//指向最后一个元素之后
	l.rbegin();	//指向最后一个元素
	l.rend();	//指向第一个元素之前
//正向遍历(从头到尾) 
	for(auto it=l.begin();it!=l.end();it++)
//反向遍历(从尾至头)
	for(auto rit=l.rbegin();rit!=l.rend();rit++)
//插入删除
	l.emplace_front(1); //"="push_front()//头插
	l.emplace_back(1); //"="push_back()//尾插
	l.pop_front(); //头删
	l.pop_back(); //尾删
	auto it=l.begin();
	l.insert(it,1);	//迭代器插入
	l.erase(it); //使迭代器失效,并返回下一个元素的迭代器 //传入反向迭代器不行 
		//*因此遍历的时候要注意不要把it直接删除导致进入死循环
	l.remove_if(x);	//删除指定元素(可多个)
//特殊
	l.sort();	//排序 //std::sort()不可以只能用这个 
	l.unique();	//去重
	l.reverse();
}

void SetTest() //集合:元素唯一性,有序性 
{ //底层实现为红黑树 
//初始化
	set<int> s;	//自定义类型的话注意要写比较函数
	int a[6]={1,3,4,5,6,7};
	set<int> s1(a,a+6);	//用数组初始化,妙呀测试不用一个个insert了 
//迭代器(和list一样) 
	s.begin();	//指向第一个元素 
	s.end();	//指向最后一个元素之后
	s.rbegin();	//指向最后一个元素
	s.rend();	//指向第一个元素之前
//正向遍历(从头到尾) 
	for(auto it=s.begin();it!=s.end();it++)
//反向遍历(从尾至头)
	for(auto rit=s.rbegin();rit!=s.rend();rit++)
//插入删除 
	s.insert(10);	//插入后自动会排序
	s.erase(x); //删除指定元素 //找到并删除成功返回值为1,否则为0 
	s.erase(it); //删除指定迭代器
		//it不会失效仍指向原元素,返回值为下一个元素迭代器   
//特殊
	s.find(x); //查找指定元素成功返回它的迭代器否则返回s.end();
	s.count(x);	//找到x返回1否则返回0
	s.lower_bound(x);	//和上面find一样 //和std::low_bound()一样 
	s.upper_bound(x); 	//找到比x大一个的并返回迭代器 
}

void Unordered_SetTest()	//无序集合(set减去排序功能) 
{	//底层基于哈希表实现 //不需要排序功能的时候优于set 
	//咋说呢,存进去是的东西是无序的所以遍历功能基本没啥用
	//但是因为是哈希结构,可以快速的查找一个元素是不是在容器内
//初始化(基本和set一样)
	unordered_set<int> us;
	//*自定义类型需要自己定义hash和qual函数 
//插入删除 
	us.emplace(x); //=insert();//返回值为pair<iterator,bool>类型
		//us中已存在x,bool则返回false,否则true,迭代器两种情况都返回指向x的迭代器
	us.erase(x);  //删除指定元素 
//查找
	us.find(x);	//找到返回x的迭代器,否则返回us.end(); 
 }
 
void MultiSetTest()	//"set减去去重的功能" 
{
	//底层和set一样都是红黑树(二叉搜索树)
//迭代器:像set一样拥有正反迭代器//反向迭代器不能被erase操作 
//删除
	multiset<int> ms={1,3,2,3,34,2};
	ms.erase(iterator);	//删除迭代器指向的位置,返回值为下一个元素的迭代器
	ms.erase(x);	//删除所有x(x可以有多个) 
//统计
	ms.count(x);	//返回值为容器内x的个数 
 }

void Unordered_MultiSetTest() //"set减去去重和排序功能" 
{
	//底层实现是哈希表
	//使用场景:可以拿来统计某种值的个数
//初始化
	unordered_multiset<int> ums; 
//统计
	ums.count();
}

void MapTest() //one to one 映射 (key to value)
{
//底层实现是红黑树
//初始化
	map<string,int> m;
//插入
	m["cjc"]=1;	//也可以insert但是这种更方便
//迭代器:拥有正反迭代器 
//查找
	m.find("key");	//找到对应key返回迭代器,否则返回m.end();
//删除
	m.erase("key");	//直接删除对应key的元素
	m.erase(iterator);	//也可以通过迭代器来删除 
}

void Unordered_MapTest() //map减去排序功能 
{
//底层实现是哈希表 //查找得很快但是建立哈希表比较耗时间 
//用法和map基本相同 
 }

void MultiMapTest() //map减去去重功能,一个key可以有多个value 
{
//实现:红黑树
//应用场景:multimap<寝室,学生> mm可以快速查到同一个寝室的学生
//查找应用
  multimap<int,string> mm;
  auto bit=mm.lower_bound(627);	//找到第一个627位置迭代器 
  auto eit=mm.upper_bound(627);	//找到最后一个627后面的位置的迭代器 
  for(auto it=bit;it!=eit;it++){
  	cout<<it->second<<" ";		//这样就找到所有627的学生了 
  }
//统计
  mm.count(keyx); //统计key==keyx键值对的总数 
//删除
  mm.erase(iterator);	//只删除迭代器指向的位置 
  mm.erase(keyx);	//删除所有key=keyx的键值对 
} 

void Unordered_MultiMapTest()	//map减去去重和key排序功能 
{//实现:哈希表 
//应用场景:需要快速查询某个键值的个数一般不用于遍历
//和umset差不多,只是多了一个映射值 
 } 
int main()
{
	return 0;
}
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值