STL容器学习总结

一、学习内容

C++ 标准模板库STL
标椎模板类对数据元素按照泛型方式处理。

1、概述

  • STL由一些可适应不同需求的集合类(collection class),以及在这些数据集合上操作的算法(algorithm)构成
  • STL内的所有组件都由模板(template)构成,其元素可以是任意类型

组件:在这里插入图片描述
STL容器类别

  • 序列式容器-排列次序取决于插入时机和位置
  • 关联式容器-排列顺序取决于特定准则
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

2、STL容器的共同操作

初始化:根据数据类型定义对象List item在这里插入图片描述
在这里插入图片描述

元素操作
指针指向元素
在这里插入图片描述

(1)迭代器

迭代器对象必须与容器类型一致在这里插入图片描述
例:

vector<char>::iterator p = v.begin();//定义迭代器p初始化为容器起始位置
p++;//将迭代器移向下一个位置
cout << *p << endl;
p++;
cout << *p << endl;
p--;//移向上一个位置
cout << *(p + 2) << endl;//输出第四个元素

迭代器示例:iterator
在这里插入图片描述
存储方式不同,操作方式相同
例:

list<int> l; 
for(pos=l.begin();pos!=l.end();++pos{}
vector<int> v; 
for(pos=v.begin();pos<v.end();++pos{}
(2)vector(序列式容器)

vector模拟动态数组
特点:
取代数组,容量可变;
有一组操作函数。

  • 必须包含的头文件#include <vector>
  • vector的大小(size)和容量(capacity)
    例:
vector<string> sentence;
sentence.reserve(5);
sentence.push_back(“hello”);
sentence.push_back(“world”);
cout <<max_size():<< sentence.max_size() << endl;
cout <<size():<< sentence.size() << endl;
cout <<capacity():<< sentence.capacity() << endl;

操作在这里插入图片描述
例:

vector<int> a;                //声明一个int型的向量a;
vector<int> a(10);            //声明一个初始大小为10的向量a;
vector<int> a(10,1);          //声明一个初始大小为10且初始值都未1的向量a;
vector<int> b(a);             //声明并用向量a初始化b;
vector<int> b(a.begin(),a.begin()+3);     
                              //声明并将向量a的第0个到第2个(共3个)作为向量b的初始值

在这里插入图片描述
例:

vector<int> a(10) ;      //大小为10的向量a
a.insert(1,3);//在第1个位置插入3
cout<<a.size()<<endl;//1
cout<<a.empty()<<endl;//ture
cout<<c.capacity();//10
a.reserve(15;//扩容为15
cout<<<c.capacity();//15

在这里插入图片描述
例:

 std::list<T> l;
 std::vector<T> v;
 …
 v.assign(l.begin(),l.end());

在这里插入图片描述
例:

std::vector<T> v;//empty
v[5]= t;			//runtime error
std::cout << v.front();	//runtime error
//----------------------------
vector<int> v;
v.reserve(10);
for(int i=0; i<7; i++) {
v.push_back(i); //在V的尾部加入7个数据
}
try {int iVal1 = v[7];
// not bounds checked - will not throw
int iVal2 = v.at(7);
// bounds checked - will throw if out of range
}
catch(const exception& e) {
cout << e.what();
}

在这里插入图片描述
例:

vector<int> a;
for (int i = 0; i < 5; ++i){
   a.push_back(5 - i); // 每次在末尾增加一元素
 }
cout << a.size() << endl;//5

在这里插入图片描述
例:

vector<int> a;
for (int i = 0; i < 5; ++i){
   a.push_back(5 - i); // 每次在末尾增加一元素
 }
cout << a.size() << endl;
a.pop_back();       //删最后一元素
a[0] = 1;          //向量可做数组使用
cout << a.size() << endl;
for (int i = 0; i < (int)a.size(); ++i){   //类型转换
    cout << a[i] << ", " << endl
}   
sort(a.begin(), a.end());
cout << "Size: " << a.size() << endl;
for (int i = 0; i < (int)a.size(); ++i){
    cout << a[i] << ", " << endl;//5432
}
cout << endl;
a.clear();
cout << "Size: " << a.size() << endl;
(3)map/multimap

通过map容器对向量输入的数据通过关键字索引,并且可用map存储
在这里插入图片描述
内部存储结构
在这里插入图片描述
特殊搜寻操作
在这里插入图片描述
例:
map

struct T1{
    int v;
    bool operator<(const T1 &a)const{
        return (v < a.v);
    }
};
struct T2{
    int v;
};
struct cmp{
    const bool operator()(const T2 &a, const T2 &b){
        return (a.v < b.v);
    }
};
int main(){
    map<T1, int>mt1; //example for user-defined class
    map<T2, int, cmp>mt2; //example for user-defined class(functor)
    map<string, int> m2;
    map<string, int>::iterator m2i, p1, p2;
    m2["abd"] = 2;
    m2["abc"] = 1;
    m2["cba"] = 2;
    m2.insert(make_pair("aaa", 9));
    m2["abf"] = 4;
    m2["abe"] = 2;
    cout << m2["abc"] << endl;
    m2i = m2.find("cba");
    if(m2i != m2.end()){
        cout << m2i->first << ": " << m2i->second << endl;
    }else{
        cout << "find nothing" << endl;
    }
    cout << "Iterate" << endl;
    for(m2i = m2.begin(); m2i != m2.end(); m2i++){
        cout << m2i->first << ": " << m2i->second << endl;
    }
}

multimap

  multimap<string, int> mm1;
  multimap<string, int>::iterator mm1i, p1, p2;
  mm1.insert(make_pair("b", 3));
  mm1.insert(make_pair("a", 0));
  mm1.insert(make_pair("b", 5));
  mm1.insert(make_pair("c", 4));
  mm1.insert(make_pair("b", 2));
  cout << mm1.size() << endl;
  for(mm1i = mm1.begin(); mm1i != mm1.end(); mm1i++){
      cout << mm1i->first << ": " << mm1i->second << endl;
      }
   cout << "COUNT: " << mm1.count("b") << endl;
   cout << "Bound: " << endl;
   p1 = mm1.lower_bound("b");
   p2 = mm1.upper_bound("b");
   for(mm1i = p1; mm1i != p2; mm1i++){
   	cout << mm1i->first << ": " << mm1i->second << endl;
    }
(4)set/multiset在这里插入图片描述

操作
在这里插入图片描述在这里插入图片描述
例:
set

struct T1{
    int key;
    int value1, value2;
    bool operator<(const T1 &b)const{
        return (key < b.key);
    }
};

struct T2{
    int key;
    int v1, v2;
};
struct T2cmp{
    bool operator()(const T2 &a, const T2 &b){
        return (a.key < b.key);
    }
};
int main(){
    set<T1> s2;
    set<T2, T2cmp> s3;

#if 1
    set<string>s1;
    set<string>::iterator iter1;
#else
    set<string, greater<string> >s1;
    set<string, greater<string> >::iterator iter1;
#endif
    s1.insert("abc");
    s1.insert("abc");
    s1.insert("abc");
    s1.insert("bca");
    s1.insert("aaa");
        cout << "ITERATE:" << endl;
    for (iter1 = s1.begin(); iter1 != s1.end(); iter1++){
        cout << (*iter1) << endl;
    }

    cout << "FIND:" << endl;
    iter1 = s1.find("abc");
    if(iter1 != s1.end()) {
        cout << *iter1 << endl;
    }else{
        cout << "NOT FOUND" << endl;
    }

    return 0;
}

multiset

int main(){
    multiset<T1> s2;
    multiset<T2, T2cmp> s3;

#if 1
    multiset<string>s1;
    multiset<string>::iterator iter1;
#else
    multiset<string, greater<string> >s1;
    multiset<string, greater<string> >::iterator iter1;
#endif
    s1.insert("abc");
    s1.insert("abc");
    s1.insert("abc");
    s1.insert("bca");
    s1.insert("aaa");
        cout << "ITERATE:" << endl;
    for (iter1 = s1.begin(); iter1 != s1.end(); iter1++)
        cout << (*iter1) << endl;
    cout << "FIND:" << endl;
    iter1 = s1.find("abc");
    if(iter1 != s1.end())
        cout << *iter1 << endl;
    else        cout << "NOT FOUND" << endl;
    cout << s1.count("abc") << endl;
    multiset<string>::iterator s1i, p1, p2;
    p1 = s1.lower_bound("abc");
    p2 = s1.upper_bound("abc");
    for(s1i = p1; s1i != p2; s1i++){
        cout << (*s1i) << endl;
    }
    return 0;
}   

pair 模板:
pair模板可以用于生成 key-value对
例:

    typedef set<double,less<double> > double_set;
	const int SIZE = 5;
	double a[SIZE] = {2.1,4.2,9.5,2.1,3.7 };
	double_set doubleSet(a,a+SIZE);
	ostream_iterator<double> output(cout," ");
	cout << "1) ";
	copy(doubleSet.begin(),doubleSet.end(),output);
	cout << endl;
	pair<double_set::const_iterator, bool> p;
	p = doubleSet.insert(9.5); 
	if( p.second ) 
		cout << "2) " << * (p.first)  << " inserted" << endl;
	else
		cout << "2) " << * (p.first)  << " not inserted" << endl;

insert函数返回值是一个pair对象, 其first是被插入元素的迭代器,second代表是否成功插入了
输出:

  1. 2.1 3.7 4.2 9.5
  2. 9.5 not inserted
(5)Algorithm(算法)
  • 泛型算法通则在这里插入图片描述在这里插入图片描述
  • count:
    size_t count(InIt first, InIt last, const T& val); //计算[first,last) 中等于val的元素个数
  • count_if
    size_t count_if(InIt first, InIt last, Pred pr); //计算[first,last) 中符合pr(e) == true 的元素 e的个数
  • min_element:
    template<class FwdIt> FwdIt min_element(FwdIt first, FwdIt last); // 返回[first,last) 中最小元素的迭代器,以 “< ”作比较器
    -max_element:
    template<class FwdIt> FwdIt max_element(FwdIt first, FwdIt last); //返回[first,last) 中最大(不小)元素的迭代器,以 “< ”作比较器
  • for_each
    template<class InIt, class Fun> Fun for_each(InIt first, InIt last, Fun f); //对[first,last)中的每个元素 e ,执行 f(e) , 要求 f(e)不能改变e
class CLessThen9  {
public:
	bool operator()( int n) { return n < 9; }
};
void outputSquare(int value ) {  cout << value * value << " "; }
}
int main() {
	const int SIZE = 10;
	 
	int a1[] = { 100,2,8,1,50,3,8,9,10,2 };
	vector<int> v(a1,a1+SIZE);
	ostream_iterator<int> output(cout," ");
	cout << endl << "2)";
	cout << count(v.begin(),v.end(),8);
	cout << endl << "3)";
	cout << count_if(v.begin(),v.end(),CLessThen9());
	cout << endl << "4)";
	cout << * (min_element(v.begin(),v.end()));
	cout << endl << "5)";
	cout << * (max_element(v.begin(),v.end()));
	cout << endl << "7) ";
	for_each(v.begin(),v.end(),outputSquare);

输出:
2)2
3)6
4)1
5)100
7) 10000 4 64 1 2500 9 64 81 100 4
排序和查找算法
在这里插入图片描述在这里插入图片描述在这里插入图片描述
例:

bool Greater10(int n)
{
	return n > 10;
}
main()  {
	const int SIZE = 10;
	int a1[] = { 2,8,1,50,3,100,8,9,10,2 };
	vector<int> v(a1,a1+SIZE);
	ostream_iterator<int> output(cout," ");
	vector<int>::iterator location;
	location = find(v.begin(),v.end(),10);
	if( location != v.end()) {
		cout << endl << "1) " << location - v.begin();
	}
	location = find_if( v.begin(),v.end(),Greater10);
	if( location != v.end())
		cout << endl << "2) " << location - v.begin();
		sort(v.begin(),v.end());
	if( binary_search(v.begin(),v.end(),9)) {
		cout << endl << "3) " << "9 found";
	}
}

输出:

  1. 8
  2. 3
  3. 9 found

二、注意事项

  • 容器类型都是泛型,元素类型要具体化
  • STL区间均为左闭右开
    半开区间[beg, end)的好处:
    1.为遍历元素时循环的结束时机提供了简单的判断依据(只要未到达end(),循环就可以继续)
    2.不必对空区间采取特殊处理(空区间的begin()就等于end())
  • 迭代器持续有效,除非发生以下两种情况
    (1)删除或插入元素
    (2)容量变化而引起内存重新分配
  • STL容器元素的条件
    必须能够通过复制构造函数进行复制
    必须可以通过赋值运算符完成赋值操作
    必须可以通过析构函数完称销毁动作
    序列式容器元素的默认构造函数必须可用
    某些动作必须定义operator ==,例如搜寻操作
    关联式容器必须定义出排序准则,默认情况是重载operator <

三、学习感受

最近开始了图书管理-后台的作业,需要用到STL方面的知识。一开始在并没有很熟练的情况下,发现自己真的是干啥啥不会,心态比较崩。代码出错的时候,就感觉自己陷入到了一个沼泽地,越改越错,通常一坐好几个小时就过去了,就很愁,特别愁,非常愁。然后我就去找百度,看关于模板库方面的资料,做好充足的准备工作后再投入到我的“编程大业”中,这时会比一开始的状态好很多很多。好像每一次做作业的过程都比较曲折,但好在运行出结果的时候,总是会恍然大悟,会很激动,然后带着这份激动继续投入到我的下一次作业中。因为刚开始敲代码比较多的这种编程作业,也在不断的适应。最后感觉自己在这一阶段的学习中跟着老师有收获到了不少,不只是在编程方面,还有在学习方面的,然后希望在往后的日子里,自己能够更加勤奋,敲代码的速度越来越快,然后编程能力越来越好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值