C++ 基础(6)STL常用容器

一. 容器基本概述

STL是C/C++开发中一个非常重要的模板,而其中定义的各种容器也是非常方便使用。STL中的常用容器包括:顺序性容器(vector、deque、list)、关联容器(map、set)、容器适配器(queue、stack)

在这里插入图片描述

二. vector

使用它时需要包含头文件:

#include<vector>

vector 的优点:

  1. 指定一块如同数组一样的连续存储,但空间可以动态扩展。即它可以像数组一样操作,并且可以进行动态操作
  2. 随机访问方便,它像数组一样被访问,即重载了 [ ] 操作符和vector.at()
  3. 节省空间,因为它是连续存储,在存储数据的区域都是没有被浪费的,但是要明确一点vector 大多情况下并不是满存的,在未存储的区域实际是浪费的

vector的缺点:

  1. 在内部插入、删除操作效率非常低,这样的操作基本上是被禁止的。Vector 被设计成只能在后端进行追加和删除操作,其原因是vector 内部的实现是按照顺序表的原理。
  2. 只能在vector 的最后进行push 和pop ,不能在vector 的头进行push 和pop
  3. 当动态添加的数据超过vector 默认分配的大小时要进行内存的重新分配、拷贝与释放,这个操作非常消耗性能。 所以要vector 达到最优的性能,最好在创建vector 时就指定其空间大小

1. vector 初始化

	vector<int> a(10); //初始化 vector 容量 为10,每个元素默认填充为0
	vector<int> b(10, 1); //每个元素默认填充为1
	vector<int> c(a); // c的拷贝构造,把a的属性赋值给c
	vector<int> d(a.begin(), a.begin() + 3); //定义了d的默认值为a中第0个到第2个(共3个)元素,并且 容量也是3
	int e[7] = {
    
     1,2,3,4,5,9,8 };
	vector<int> f(e, e + 6); //初始数据为 从数组中0到5(共6个)个元素,容量也是6

2. 常用函数

    vector<int> a;
    vector<int> ::iterator iter = a.begin(); //获取迭代器首地址
    vector<int> ::const_iterator const_iter = a.begin(); //获取const类型迭代器 只读
    vector<int> ::const_iterator end_iter = a.end(); // 获取最后一个元素迭代器的下一个地址一
    a.push_back(100); //尾插
    a.pop_back(); //尾删
    int size = a.size(); //个数
    int capacity = a.capacity(); //容量
    bool isEmpty = a.empty(); //判断是否为空
    cout << a[0] << endl; //取得第一个元素
    a.insert(a.end(), 5, 3); //从a.end位置插入5个值为3的元素
    a.erase(a.begin(), a.begin() + 2); //删除a[0]-a[2]之间的元素,不包括a[2],其他元素前移
    a.clear(); //清空

3. 遍历

    vector<int> a(10);
    // for循环
    for (int i = 0; i < a.size(); i++)
    {
    
    
        cout << a[i] << endl;
    }
    //迭代器法
    for (vector<int> ::iterator iter = a.begin(); iter != a.end(); iter++)
    {
    
    
        cout << *iter << endl;
    }

三. deque

队列容器允许从一端新增元素,从另一端移除元素
队列中只有队头和队尾才可以被外界使用,因此队列不允许有遍历行为
队列中进数据称为 — 入队 push
队列中出数据称为 — 出队 pop
在这里插入图片描述

deque和vector类似,支持快速随机访问。二者最大的区别在于,vector只能在末端插入数据,而deque支持双端插入数据。deque的内存空间分布是小片的连续,小片间用链表相连,实际上内部有一个map的指针。deque空间的重新分配要比vector快,重新分配空间后,原有的元素是不需要拷贝的

   deque<int> d;
    //d.assign(10, 2); //将10个值为2的元素赋到deque中 
    // d.assign(d1.begin(), d1.end());  //接受序列容器的范围
    //d.push_back(999); // 尾添
    //d.push_front(666); // 首添
    for (int i = 0; i < 100; i++)
    {
    
    
        d.push_back(i);
    }
    d.insert(d.begin() + 3, 99); //99 插入到 v 的第四个元素,后面的元素后移
    d.insert(d.end() - 3, 9999); // 99插入到 v的倒数第四个元素
    for (deque<int>::iterator it = d.begin(); it != d.end(); it++)
    {
    
    
        cout << *it << endl;
    }
    d.pop_front(); // 首删
    d.pop_back(); // 尾删
    d.erase(d.begin() + 3); // 删除v 的第四个元素
    d.erase(d.begin(), d.begin() + 3); // 删除前三个
    d.front(); // 返回首个
    d.back(); // 返回最后一个
    d.clear();
    cout << d.size() << endl;  //0 

四. map/ multimap

简介:

  • map中所有元素都是pair
  • pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
  • 所有元素都会根据元素的键值自动排序

优点:

  • 可以根据key值快速找到value值

map和multimap区别

  • map不允许容器中有重复key值元素
  • multimap允许容器中有重复key值元素

map/multimap属于关联式容器,底层结构是用二叉树实现

   map<int, string> map1;
    // 常用操作方法
    map1[3] = "Saniya"; //向下标为3的区域添加元素
    map1.insert(pair<int, string>(1, "Siqinsini")); //pair方式插入元素
    map1.insert(map<int, string> ::value_type(2, "Diyabi")); //value_type方式入元素
    map1.insert(make_pair<int, string>(4, "V5")); //make_pair插入元素
    string value = map1[3]; //数值方式获取元素,根据key取得value,key不能修改

    map<int, string> ::iterator iter = map1.begin();//取得迭代器首地址
    int key = iter->first; //第一个属性 key
    string value = iter->second; //第二个属性 得value
    map1.erase(iter); //通过迭代器删除
    map1.erase(3); //根据key删除value
    map1.size(); //元素个数
    map1.empty(); //判断空
    map1.clear(); //清空所有元素
    //遍历
    for (map<int, string> ::iterator iter = map1.begin(); iter != map1.end(); iter++)
    {
    
    
        int k = iter->first;
        string v = iter->second;
        cout << k << " " << v << endl;
    }

五. set/ multiset

所有元素都会在插入时自动被排序
set/multiset属于关联式容器,底层结构是用二叉树实现

set和multiset区别

  • set不允许容器中有重复的元素
  • multiset允许容器中有重复的元素
	set<int> s;
	s.insert(10);
	s.insert(30);
	s.insert(20);
	s.insert(40);
	for (set<int>::iterator it = s.begin();  it != s.end(); it++)
	{
    
    
		cout << *it << endl;
	}
	s.size(); //返回容器中元素的数目
	s.empty(); //判断容器是否为空
	s.clear(); //清除所有元素 
	s.erase(++s.begin()); //删除pos迭代器所指的元素,返回下一个元素的迭代器
	s.erase(20); //  //删除容器中值为20的元素
	s.erase(s.begin(), s.end()); // 删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器
	s.find(30);  //查找30是否存在,若存在,返回该元素的迭代器;若不存在,返回set.end()
	s.count(40); //统计40 出现的个数

六. list

功能: 将数据进行链式存储

链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的

链表的组成:链表由一系列结点组成

结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域

STL中的链表是一个双向循环链表
在这里插入图片描述

	list<int> l;
	l.push_back(10);
	l.push_back(20);
	l.push_back(30);
	l.push_back(40);
	list<int> l2 (l.begin(), l.end()); // 根据区间赋值
	l.push_back(60); // 尾添
	l.push_front(70); // 首添
	l.pop_back(); // 尾删
	l.pop_front(); // 首删
	l.insert(l.begin(), 11);//在迭代器位置插入10,返回新数据的位置
	l.insert(l.begin(),2, 11);//在迭代器位置插入两个10,无返回值
	l2.swap(l); // 交换
	l.size(); // 大小
	l.empty(); // 是否为空
	l.resize(10); // 重新指定大小
	l.clear(); // 移除容器的所有数据
	l.remove(10); //删除容器中所有与10匹配的元素

猜你喜欢

转载自blog.csdn.net/haiyanghan/article/details/113155637