STL(c++标准库)

容器

容器都是类模板,实例化后称为容器类,用容器类定义的对象称为容器对象

ps:用vector来解释一下
vector是一种顺序容器vector< int > 是容器类的名称vector< int > a则定义了一个容器类对象a

顺序容器

元素在容器中的位置与元素的值是无关的,容器不是排序的,可以在任和指定位置插入元素

顺序容器有vector(可变长数组),deque(双端队列),list(双向链表)

ps:vector和deque可以实现随机存取

vector

引用头文件vector

vector作为一种可变长的动态数组,可以根据需要自行分配空间,但是好像不会回收,用成员函数capacity()可以看出来。

下面是常用的成员函数:

size():返回元素个数
capacity():返回数组分配的空间
empty():检查是否为空,bool类型
end()begin():返回数组的终止和起始迭代器
push_back()pop_back():在数组的尾部添加或删除元素
insert(position, first, last)erase(sirst, last):向数组某一位置插入或删除若干元素
front()back():返回对数组第一个和最后一个元素的引用

使用示例:

#include<iostream>
#include<vector>

using namespace std;

int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    vector<int> dyarray(a, a+5);        
    //函数原型是vector(iterator first, iterator last),相当于把其他容器的[first, last)赋值给vector容器
    //iterator是指迭代器
    cout << dyarray.end() - dyarray.begin() << endl;
    cout << dyarray.size() << endl;     //返回数组中元素的个数
    cout << dyarray.empty() << endl;        //(bool)是否为空
    dyarray.push_back(111);     //在数组的尾部添加
    dyarray.pop_back();     //删除末尾的元素
    dyarray.insert(dyarray.begin() + 1, a + 1, a + 3);       
    //向vector数组的某一位置插入若干元素,原型:insert(position, first, last)
    dyarray.erase(dyarray.begin() + 1, dyarray.begin() + 3);
    //删除vector数组某一位置的若干元素,原型:erase(first, last)
    cout << dyarray.front() << " " << dyarray.back() << endl;
    //front()返回对数组第一个元素的引用,back()返回最后一个
    cout << dyarray.capacity() << endl;

    //二维数组的声明
    //主索引大小要给出(跟二维数组的声明是一样的),如果需要变长再手动加
    vector< vector<int> > v(3);
    for(int i = 0; i < 3;i++)
    {
        for(int j = 0;j < 5;j++)
            v[i].push_back(j);
    }
    for(int i = 0; i < 3;i++)
    {
        for(int j = 0;j < 5;j++)
            cout << v[i][j] << " ";
        cout << endl;
    }
    cout << v.size() << endl;       //返回值是3
    return 0;
}

list

引用头文件list

list是对应双向链表的容器,增删元素只要修改指针即可,但是不能进行随机存取。

与vector有许多类似的成员函数,以及一些独有的成员函数,如下:
push_back()pop_back():在尾部增删元素
push_front()pop_front():在头部增删元素
sort():将链表中的元素按从小到大排序
与后面的算法sort不同,对于vector和deque这种支持随机访问的容器,可以直接用算法sort进行排序,但是list不支持随机访问,所以在成员函数中实现了排序
remove(const T &val):删除和常量参数相等的元素
unique():删除和前一个元素相同的元素(只有当队列有序的时候才能实现去重)
merge(list &x):将两个有序的链表合并,合并后依旧有序
splice(list::iterator i, list &x, first, last):将链表x的[first, last)剪切到原链表迭代器的位置之前
使用示例如下:

#include<iostream>
#include<list>

using namespace std;

void Printf(list<int> l)
{
    for(list<int>::iterator i = l.begin();i != l.end();i++)
        cout << *i << " ";
}

int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    list<int> l(a, a + 5);      //赋值加初始化,和vector一样
    l.push_front(0);        //在头部插入
    l.push_back(5);     //在尾部插入
    
    l.pop_front();      //删除头部元素
    l.remove(5);        //删除与参数相等的元素,函数原型:void remove(const T &val)
    
    int b[5] = {3, 4, 5, 5, 6};
    list<int> l_2(b, b + 5);
    l_2.reverse();      //将链表的排序逆向
    l_2.sort();     //将队列从小到大排序
    l.merge(l_2);       //将两个有序的双向链表合并,合并后依旧有序
    //l:1, 2, 3, 3, 4, 4, 5, 6
    l.unique();     //删除所有和前一个元素相同的元素,对于已经有序的链表可以直接实现去重
    //l:1, 2, 3, 4, 5, 6
    l.push_back(3);
    l.unique();
    //l:1, 2, 3, 4, 5, 6, 3

    l.insert(l.end(), a + 1, a + 2);        //在某一位置插入,用法和vector相同
    list<int>::iterator pos = find(l.begin(), l.end(), 6);
    //可以使用find函数对链表进行查找,返回值是迭代器
    l.splice(l.begin(), l_2, l_2.begin(), l_2.end());
    //函数原型为:splice(list<T>::iterator, list<T> &x, first, end)
    //将队列x的[first, last)剪切到原链表迭代器的位置之前
    return 0;
}

deque

deque的实现形式同样是一种可变长的动态数组,与vector容器不同的是,vector容器在头部增删元素比较浪费时间(因为是顺序存储,除了在头部的操作外还要逐个移动后面的元素,因此时间复杂度就与元素个数有关)而deque在头部的增删元素也能像尾部一样,只用常数时间就能完成

deque的成员函数与vector进本没有区别,两个独有的在头部增删的成员函数:
push_front()pop_front():在头部增删元素

关联容器

关联容器有一对键值对(key - value),key是键值,value是实值,容器中的元素按照键值根据某种规则排序(比如一般是从小到大)。

相比于顺序容器,关联容器内的元素是排序的,因为对元素的(键)值进行修改之后,容器不会对元素进行重新排序,所以修改元素要先删除原有的再重新添加新的元素。

关联容器有:
set:只有一组值,既是实值也是键值,不允许有重复元素
multiset:与set基本相同,允许有重复元素
map:map中的所有元素都是键值对(pair),不允许有重复的键值
multimap:与map基本相同,允许有重复元素

pair类模板

pair类模板拥有两个值,之前提过的键值对就可以看作是pair类,键值和实值就是pair的两个值。

为了避免大量重复的代码,我们引入了函数模板template,简单提示一下:

template <typename T>
T Max_Value(T first, T second)
{
	if(first > second)
		return first;
	else return second;
}

当传给函数的参数是两种不同的数据类型时,编译器会由于找不到合适的匹配类型而报错,这是引入pair类模板有时可以解决一些问题。

pair的一些用法如下:

#include<iostream>

using namespace std;

int main()
{
    pair<int, double> p_1;      //p_1:<0, 0>
    pair<int, int> p_2(pair<char, char>('a', 'b'));     //p_2:<97, 98>
    pair<int, string> p_2 = make_pair(200, "hello");
    cout << p_1.first << "," << p_1.second << endl;
    //用first和second可以访问pair类的两个值
    return 0;
}

multiset

multimap

set

map

迭代器

迭代器类似于指针,通过迭代器可以访问容器中的元素;某些时候迭代器和数组中的索引很像

已经见过的,例如vector变量v的成员函数v.begin()就是迭代器的一种,返回的是容器第一个元素的“指针”

迭代器的定义方法:
■正向迭代器:
容器类名::iterator 迭代器名
ex:vector::iterator i
这是一个未初始化的vector容器的正向迭代器
■常量正向迭代器:
容器类名::const_iterator 迭代器名
■反向迭代器:
容器类名::reverse_iterator 迭代器名
■反向常量迭代器:
容器类名::const_reverse_iterator 迭代器名

迭代器的使用基本上和数组的索引,指针没有太大区别,++的使用也是一样的,但是正向迭代器和反向迭代器的方向相反。

示例:

#include<iostream>
#include<vector>

using namespace std;

int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    vector<int> v(a, a+5);        
    vector<int>::iterator i;        //正向迭代器
    for(i = v.begin();i < v.end();i++)      //作为索引
        cout << *i << " ";      //类似指针
    
    for(vector<int>::reverse_iterator j = v.rbegin();j != v.rend();j++)      
    //反向迭代器
        cout << *i << " ";
    return 0;
}

ps:反向迭代器循环继续的条件是j != v.rend(),这一点在双向迭代器中也是一样

事实上常用的迭代器有三种:正向,双向,随机访问
双向迭代器是有- -功能的;有随机访问功能的除了支持==!=还支持用>, <等来比较

不同容器的迭代器功能如下:

容器迭代器功能
vector随机访问
deque随机访问
list双向
set/multiset双向
map/multimap双向
stack不支持迭代器
queue不支持迭代器
priority_queue不支持迭代器

算法

引用头文件algorithm

STL里有一些已经实现好的常用算法,最常使用的两个:
sort():将容器内的元素按照从小到大排序
值得注意的是,算法中的sort()函数只能对可以实现随机访问的容器进行排序,对于list,可以使用内部实现的成员函数来达到排序的目的
find(first, end, const T &val):在[first, end)区间内寻找与val相等的元素,返回值是指针类型(对于数组来说)或者迭代器(对于容器来说)
用法示例:

#include<iostream>
#include<algorithm>     //使用STL的算法
#include<vector>
#include<list>

using namespace std;

int main()
{
    int a[5] = {2, 1, 4, 3, 5};
    sort(a, a + 5);
    for(int i = 0 ;i < 5;i++)
        cout << a[i] << " ";
    cout << endl;
    //1 2 3 4 5
    vector<int> v(a, a + 5);
    sort(v.begin(), v.end());       //算法中的sort()函数

    list<int> l(a, a + 5);
    l.sort();       //list容器的成员函数

    int* pos_0 = find(a, a + 5, 5);
    vector<int>::iterator pos_1 = find(v.begin(), v.end(), 5);
    list<int>::iterator pos_2 = find(l.begin(), l.end(), 5);
    //用find()函数,返回值是指针或者迭代器
    cout << *pos_0 << " " << *pos_1 << " " << *pos_2 << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值