c++STL概述

news2024/11/24 19:35:36

目录

STL基本概念

STL六大组件

STL的优点

STL三大组件

容器

算法

迭代器

普通的迭代器访问vector容器元素

算法for_each实现循环

迭代器指向的元素类型是自定义数据类型

迭代器指向容器

常用容器

string容器

string的基本概念

string容器的操作

string的构造函数

string基本赋值操作

string的存取字符串操作

string拼接操作

string的查找与替换

string比较操作

string子串

string插入和删除操作

string对象的类型转换

vector容器

vector容器基本概念

vector的数据结构

vector的构造函数

vector常用赋值操作

vector大小操作

vector容器数据存储操作

vector容器的插入和删除

利用swap收缩空间

deque容器

deque容器基本概念

deque容器的实现原理

deque的api—构造函数

deque的aip—赋值操作

deque的api—容器的大小操作

deque的api—双端的插入和删除

deque的api—数据存储

deque的api—插入操作

deque的api—删除操作


STL基本概念

STL(Standard Template Library,标准模板库),是惠普实验室开发的一系列软件的统
称。现在主要出现在c++中,但是在引入c++之前该技术已经存在很长时间了。
STL从广义上分为:容器(container)算法(algorithm)迭代器(iterator),容器和算法之间通过迭代器进行无缝连接。STL 几乎所有的代码都采用了模板类或者模板函数,这相比传统的由函数和类组成的库来说提供了更好的代码重用机会。STL(Standard Template Library)标准模板库,在我们c++标准程序库中隶属于STL的占到了80%以上。

STL六大组件

容器:保存数据的空间结构,如vector、list、deque、set、map等

算法:特定的的求解步骤,如sort、find、copy、for_each。

迭代器:本质是一个指针

仿函数:函数对象,重载了operator()的类

适配器:一种用来修饰容器或者仿函数或迭代器接口的东西。

空间配置器:负责内存空间的申请 释放 管理等

STL的优点

STL 具有高可重用性,高性能,高移植性,跨平台的优点。
高可重用性:STL中几乎所有的代码都采用了模板类和模版函数的方式实现,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。
高性能:如map 可以高效地从十万条记录里面查找出指定的记录,因为map 是采用红黑树的变体实现的。

STL三大组件

容器

保存数据的(数据结构)

常用的数据结构:数组(array),链表(list),tree(树),栈(stack),队列(queue),集合(set),映射表(map),根据数据在容器中的排列特性,这些数据分为序列式容器和关联式容器两种。
序列式容器强调值的排序,序列式容器中的每个元素均有固定的位置,除非用删除或插入的操作改变这个位置。Vector容器、Deque容器、List容器等。
关联式容器是非线性的树结构,更准确的说是二叉树结构。各元素之间没有严格的物理上的顺序关系,也就是说元素在容器中并没有保存元素置入容器时的逻辑顺序。关联式容器另一个显著特点是:在值中选择一个值作为关键字key,这个关键字对值起到索引的作用,方便查找。Set/multiset 容器 Map/multimap容器

算法

以有限的步骤,解决逻辑或数学上的问题,这一门学科我们叫做算法(Algorithms).
广义而言,我们所编写的每个程序都是一个算法,其中的每个函数也都是一个算法,毕竟它们都是用来解决或大或小的逻辑问题或数学问题。STL收录的算法经过了数学上的效能分析与证明,是极具复用价值的,包括常用的排序,查找等等。特定的算法往往搭配特定的数据结构,算法与数据结构相辅相成。
算法分为:质变算法和非质变算法。质变算法:指运算过程中会改变该区间内的元素的内容,如拷贝替换删除等。非质变算法:是指运算过程中不会改变该区间内的元素的内容,如查找遍历计数等。

迭代器

普通的迭代器访问vector容器元素

#include <iostream>
#include <string.h>
#include <iterator>
#include <vector>
using namespace std;

void test01()
{
    vector<int> v;
    v.push_back(2);
    v.push_back(5);
    v.push_back(4);
    v.push_back(7);
    //若需要访问容器内的元素 需要拿到容器首元素的迭代器(指针)
    vector<int>::iterator it_s = v.begin();
    vector<int>::iterator it_e = v.end();
    for(;it_s != it_e;it_s++)
    {
        cout << *it_s<< " ";
    }
    cout << endl;

}

int main()
{
    test01();
    return 0;
}

算法for_each实现循环

void printf(int a)
{
 cout<< a << endl;
}
void test01()
{
    vector<int> v;
    v.push_back(2);
    v.push_back(5);
    v.push_back(4);
    v.push_back(7);
    //若需要访问容器内的元素 需要拿到容器首元素的迭代器(指针)
    vector<int>::iterator it_s = v.begin();
    vector<int>::iterator it_e = v.end();
    /*for(;it_s != it_e;it_s++)
    {
        cout << *it_s<< " ";
    }*/
    cout << endl;
    for_each(it_s,it_e,printf);//头地址 尾地址 回调函数

}

迭代器指向的元素类型是自定义数据类型

#include <iostream>
#include <string.h>
#include <iterator>
#include <vector>
using namespace std;

class person
{
public:
    person(int age)
    {
        this->age = age;
    }
    int age;

};
void printf(person &p)
{
    cout << p.age << endl;
}
void test01()
{
    person p1(1);
    person p2(2);
    person p3(3);
    person p4(4);

    vector<person> v;
    v.push_back(p1);
    v.push_back(p2);
    v.push_back(p3);
    v.push_back(p4);

    vector<person>::iterator it_s = v.begin();
    vector<person>::iterator it_e = v.end();
    for(;it_s != it_e;it_s++)
    {
        //对容器取* 得到的是<>里的类型
        printf(*it_s);
    }
    cout << endl;
}

迭代器指向容器

#include <iostream>
#include <string.h>
#include <iterator>
#include <vector>
using namespace std;

void test01()
{
    vector< vector<int> > v;//数据类型为容器的容器
    vector<int> v1;
    vector<int> v2;
    vector<int> v3;
    for(int i = 0;i<3;i++)
    {
		v1.push_back(i);//小容器v1尾部插入 0 1 2
		v2.push_back(i+10);//v2尾部插入 10 11 12
		v3.push_back(i+100);//v3尾部插入 100 101 102
	}
	//小容器插入大容器
	v.push_back(v1);
	v.push_back(v2);	
	v.push_back(v3);
	
    vector<vector<int>>::iterator it = v.begin();//大容器头地址
    for(;it!=v.end();it++ )
    {
        //*it得到的是<vector<int>>
        vector<int>::iterator it1 = (*it).begin();//小容器头
        vector<int>::iterator it2 = (*it).end();//尾
        for(;it1!=it2;it1++)
        {
            cout<< *it1 << endl;
        }
    }

}

int main()
{
    test01();
    return 0;
}

常用容器

string容器

string的基本概念

string容器是一个类 容器中有一个指针 指针维护了一个数组

string容器提供了copy find insert replace等功能

string容器的操作
string的构造函数

        string();//创建一个空的字符串 例如: string str;
        string(const string& str);//使用一个string对象初始化另一个string对象
        string(const char* s);//使用字符串s初始化
        string(int n, char c);//使用n个字符c初始化v

#include <iostream>
#include <string.h>
#include <iterator>
#include <vector>
#include <string>
using namespace std;

void test01()
{
    string str;
    string str1("hello");
    string str2(str1);
    string str3(5,'k');
    cout << str1 << endl;
    cout << str2 << endl;
    cout << str3 << endl;
}

int main()
{
    test01();
    return 0;
}

编译运行

string基本赋值操作

string& operator=(const char* s);//char*类型字符串 赋值给当前的字符串
string& operator=(const string &s);//把字符串s 赋给当前的字符串
string& operator=(char c);//字符赋值给当前的字符串
string& assign(const char *s);//把字符串s 赋给当前的字符串
string& assign(const char *s, int n);//把字符串s的前n个字符赋给当 当前的字符串string& assign(const string &s);//把字符串s 赋给当前字符串
string&assign(int n, char c);//用n个字符c 赋给当前字符串
string& assign(const string &s, int start, int n);//将s从start 开始n个字符赋值给字符4

#include <iostream>
#include <string.h>
#include <iterator>
#include <vector>
#include <string>
using namespace std;

void test01()
{
	string str("helloworld");
	string str1("heihei");
	str = str1;
	str = "hehe";
	str = 'c';
	str.assign(str1);
	str.assign("jack");
	str.assign("jack",2);	
	cout << str << endl;
	str.assign(5,'c');
	cout << str << endl;	
	str.assign(str1,2,3);
	cout << str << endl;
}

int main()
{
    test01();
    return 0;
}

编译运行

string的存取字符串操作

char& operator[](int n);//通过[]方式取字符串

char& at(int n);//通过at方法获取字符

#include <iostream>
#include <string.h>
#include <iterator>
#include <vector>
#include <string>
using namespace std;

void test01()
{
	string str("helloworld");
	cout << str[4] << endl;//输出o
	str[4] = 'c';
	cout << str.at(4)<< endl;//输出c
}

int main()
{
    test01();
    return 0;
}
string拼接操作

string& operator+=(const string& str);//重载+=操作符

string& operator+=(const char* str);//重载+=操作符

string& operator+=(const char c);//重载+=操作符

string& append(const char *s);//把字符串s连接到当前字符串结尾

string& append(const char *s, int n);//把字符串s的前n个字符连接到当前字符串结尾

string& append(const string &s);//同operator+=()

string& append(const string &s,int pos,int n)//把字符串s中从pos开始的n个字符连接到当前字符串尾

string& append(int n,char c);//在当前字符串结尾添加n个字符c

#include <iostream>
#include <string.h>
#include <iterator>
#include <vector>
#include <string>
using namespace std;

void test01()
{
	string str1("helloworld");
	cout << str1 << endl;

	string str2("123456789");
	str1 += str2;
	cout << str1 << endl;

	str1 += "hehe";
	cout << str1 << endl;

	str1 += 'c';
	cout << str1 << endl;

	str1.append("hehe");
	cout << str1 << endl;

	str1.append("hehe",2);
	cout << str1 << endl;

	str1.append(str2,2,3);
	cout << str1 << endl;
}

int main()
{
    test01();
    return 0;
}

编译运行

string的查找与替换

int find(const string& str, int pos =0) const;//查找str第一次出现位置,从pos开始查找

int find(const char* s, int pos =0) const; //查找s第一次出现位置,从pos开始查找

int find(const char* s, int pos, int n) const;//从pos 位置查找s的前n个字符第一次位置

int find(const char c, int pos = 0) const; //查找字符c第一次出现位置

int rfind(const string& str, int pos = npos) const;//查找str最后一次位置,从pos开始查找

int rfind(const char* s, int pos = npos) const;//查找s最后一次出现位置,从pos开始查找

int rfind(const char* s, int pos, int n) const;//从pos 查找s的前n个字符最后一次位置

int rfind(const char c, int pos =0) const;//查找字符c最后一次出现位置

string& replace(int pos, int n, const string& str);//替换从pos开始n个字符为字符串

strstring& replace(int pos, int n, const char* s);//替换从pos开始的n个字符为字符串s

#include <iostream>
#include <string.h>
#include <iterator>
#include <vector>
#include <string>
using namespace std;

void test01()
{
    string str1("helloworld");
    string str2("wor");

    cout << str1.find(str2)<< endl;
    cout << str1.find("wor")<< endl;
    cout << str1.find("world",0,2)<< endl;
    cout << str1.find('o')<< endl;
    cout << str1.rfind("rl")<< endl;//rfind 从右往左查
    str1.replace(2,4,str2);
    cout << str1 << endl;
}

int main()
{
    test01();
    return 0;
}

编译运行

string比较操作

compare函数在>时返回1,<时返回-1,==时返回0

比较区分大小写,比较时参考字典顺序,排前面的小 大写的A比小写的a小

int compare(const string &s) const;//与字符串s比较

int compare(const char *s) const;//与字符串s比较

void test01()
{
    string str1("helo");
    string str2("world");
    cout << str1.compare(str2) << endl;//输出-1
}

string子串

string substr(int pos = 0,int n = npos);//返回由pos开始的n个字符组成的字符串

void test01()
{
    string str1("heloworld");
    cout << str1.substr(4,3) << endl;//输出wor
}

string插入和删除操作

string& insert(int pos, const char* s);//插入字符串

string& insert(int pos, conststring& str);//插入字符串

string& insert(int pos,int n,char c);//在指定位置插入n个字符串c

string& erase(int pos. int n,char c);//指定位直插入n个字符c

string& erase(int pos, int n =npos);//删除从Pos开始的n

#include <iostream>
#include <string.h>
#include <iterator>
#include <vector>
#include <string>
using namespace std;

void test01()
{
    string str1("helloworld");
    str1.insert(2,"kk");
    cout << str1 << endl;

    string str2("helloworld");
    string str("hello");
    str2.insert(2,str);
    cout << str2 << endl;

    string str3("helloworld");
    str3.insert(2,10,'r');
    cout << str3 << endl;

    string str4("helloworld");
    str4.erase(3,3);
    cout << str4 << endl;
}

int main()
{
    test01();
    return 0;
}

编译运行

string对象的类型转换

//string 转 char*
string str= "itcast";
const char* cstr =str.c_str();
//char* 转 string
char*s ="itcast";
string str(s);
在c++中存在一个从const char到string的隐式类型转换,却不存在从一个string对象到Cstring的自动类型转换。对于string类型的字符串,可以通过cstr()函数返回string对象对应的C_string.
通常,程序员在整个程序中应坚持使用string类对象,直到必须将内容转化为char时才将其转换为C_string.

提示:
为了修改 string字符串的内容,下标操作符[]和 at 都会返回字符的引用。但当字符串的内存被重新分配之后,可能发生错误.

void test01()
{
    string str("helloworld");    
    str = "world";//调用str.operator=(char *)

    char *s = NULL;
    //str.c_str();//得到const char *
    //去const
    s = cosnt cast<char *>(str.c_str());
}

vector容器

vector容器基本概念

向量 vector是一种对象实体, 能够容纳许多其他类型相同的元素, 因此又被称为容器。 与string相同, vector 同属于STL(Standard Template Library, 标准模板库)中的一种自定义的数据类型, 可以广义上认为是数组的增强版。在使用它时, 需要包含头文件  #include<vector>。vector 容器与数组相比其优点在于它能够根据需要随时自动调整自身的大小以便容下所要放入的元素。此外, vector 也提供了许多的方法来对自身进行操作。

vector 型变量的声明以及初始化的形式也有许多, 常用的有以下几种形式

vector<int> a ; //声明一个int型向量a

vector<int> a(10) ; //声明一个初始大小为10的向量

vector<int> a(10, 1) ; //声明一个初始大小为10且初始值都为1的向量

vector<int> b(a) ; //声明并用向量a初始化向量b

vector<int> b(a.begin(), a.begin()+3) ; //将a向量中从第0个到第2个(共3个)作为向量b的初始值

 除此之外, 还可以直接使用数组来初始化向量:

int n[] = {1, 2, 3, 4, 5} ; vector<int> a(n, n+5) ; //将数组n的前5个元素作为向量a的初值 
vector<int> a(&n[1], &n[4]) ; //将n[1] - n[4]范围内的元素作为向量a的初值
vector的数据结构

Vector所采用的数据结构非常简单,线性连续空间,它以两个迭代器Myfirst和Mylast分别指向配置得来的连续空间中目前已被使用的范围,并以迭代器_Myend指向整块连续内存空间的尾端。
为了降低空间配置时的速度成本,vector实际配置的大小可能比客户端需求大一些,以备将来可能的扩充,这边是容量的概念。换句话说,一个vector的容量永远大于或等于其大小,一旦容量等于大小,便是满载,下次再有新增元素,整个vector容器就得另觅居所。
注意:
所谓动态增加大小,并不是在原空间之后续接新空间(因为无法保证原空间之后尚有可配置的空间),而是一块更大的内存空间,然后将原数据拷贝新空间,并释放原空间。因此,对vector的任何操作,一旦引起空间的重新配置,指向原vector的所有迭代器就都失效了。这是程序员容易犯的一个错误,务必小心。

vector的构造函数

vector<T>v;//采用模板实现类实现,默认构造函数

vector(v.begin(), v.end());//将头和尾区间中的元素拷贝给本身

vector(n, elem);//构造函数将n个elem拷贝给本身

vector(const vector &vec);//拷贝构造函数

void printf(int a)
{
    cout << a << endl;
}

void test01()
{
    vector<int> v1;
    v1.push_back(1);    
    v1.push_back(2);
    v1.push_back(3);
    v1.push_back(4);
    //vector<int> v2(v1);
    //vector<int> v2(v1.begin(), v1.end());//将头和尾区间中的元素拷贝给本身    
    vector<int> v2(v1.begin()+1, v1.end());//将头和尾区间中的元素拷贝给本身
    for_each(v2.begin(),v2.end(),printf);
}

vector常用赋值操作

assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。

assign(n, elem);//将n个elem拷贝赋值给本身。

vector&operator=(const vector &vec);//重载等号操作符

swap(vec);//将vec与本身的元素互换。

void printf(int a)
{
    cout << a << endl;
}

void test01()
{
    vector<int> v1;
    v1.push_back(1);    
    v1.push_back(2);
    v1.push_back(3);
    v1.push_back(4);
    
    vector<int> v2;
    v1.push_back(5);    
    v1.push_back(6);
    v1.push_back(7);
    v1.push_back(8);
    //v2.assign(v1.begin(),v1.end());//将[beg, end)区间中的数据拷贝赋值给本身
    //v2.assign(10,5);//将n个elem拷贝赋值给本身
    //v2 = v1;//重载等号操作符
    v2.swap(v1);//v1和v2的指针指向交换
  
    for_each(v2.begin(),v2.end(),printf);
}

vector大小操作

size();//返回容器中元素的个数
empty();//判断容器是否为空
resize(int num);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
resize(int num, elem);//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
capacity();//容器的容量
reserve(int Len);//容器预留Len个元素长度,预留位置不初始化,元素不可访问。

void printf(int a)
{
	cout << a << endl;
}

void test01()
{
	vector<int> v1;
	v1.push_back(1);	
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);

	cout << v1.size() << endl;//大小
	cout << v1.capacity() << endl;//容量
	v1.resize(10);
	if(!v1.empty())
	{
		cout << "不为空" << endl;
	}
	for_each(v1.begin(),v1.end(),printf());//1234000000
	
	vector<int> v2;
	v2.reserve(1000);//为v2预留1000个空间 设置容量
	cout << v2.size() << endl;//0
	cout << v2.capacity() << endl;//1000
}
vector容器数据存储操作

at(int idx);//返回索引idx 所指的数据,如果idx 越界, 抛出out_of_range异常。

operator[];//返回索引idx所指的数据,越界时 运行直接报错

front();//返回容器中第一个数据元素

back();//返回容器中最后一个数据元素

#include <iostream>
#include <string.h>
#include <iterator>
#include <vector>
#include <string>
using namespace std;

void printf(int a)
{
    cout << a << endl;
}

void test01()
{
    vector<int> v1;
    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(3);
    v1.push_back(4);

    cout << v1.at(2) << endl;//3
    cout << v1[2] << endl;//3
    cout << v1.front() << endl;//1
    cout << v1.back() << endl;//4
}

int main()
{
    test01();
    return 0;
}
vector容器的插入和删除

insert(const_iterator pos, int count,ele 一 代器指向位置pos插入count 个元素ele.push_back(ele);//尾部插入元素ele
pop_back();//删除最后一个元素
erase(const_iterator start, const_iterator end);//删除迭代器从start 到end之间的元erase(const_iterator pos);//删除迭代器指向的元素
clear();//删除容器中所有元素

利用swap收缩空间

swap收缩空间的本质是指针指向了不同的容器 

#include <iostream>
#include <string.h>
#include <iterator>
#include <vector>
#include <string>
#include <iostream>
#include <vector>
#include <string>
using namespace std;

void test01()
{
    vector<int> v1;
    for (int i = 0; i < 1000; i++)
    {
        v1.push_back(i);
    }
    cout << v1.size() << " " << v1.capacity() << endl;//1000 1024
    v1.resize(10);//
    cout << v1.size()<< " " << v1.capacity() << endl;//10 1024
    vector<int>(v1).swap(v1);
    cout << v1.size()<< " " << v1.capacity() << endl;//10 10

}

int main()
{
    test01();
    return 0;
}

deque容器

deque容器基本概念

Deque 容器和vector容器最大的差异,一在于deque允许使用常数项时间对头端进行元素的插入和删除操作。二在于deque没有容量的概念,因为它是动态的以分段连续空间组合而成,随时可以增加一段新的空间并链接起来,换句话说,像vector那样,”旧空间不足而重新配置一块更大空间,然后复制元素,再释放旧空间”这样的事情在deque身上是不会发生的。也因此,deque没有必须要提供所谓的空间保留(reserve)功能.
虽然deque容器也提供了Random Access lterator,但是它的迭代器并不是普通的指针,其复杂度和vector不是一个量级,这当然影响各个运算的层面。因此,除非有必要,我们应该尽可能的使用vector,而不是deque。对deque进行的排序操作,为了最高效率,可将deque先完整的复制到一个vector中,对vector容器进行排序,再复制回deque

        双端数组deque和vector的区别

        vector对于头部的插入效率低,数据量越大,效率越低

        deque相对而言,对头部的插入删除速度会比vector快

        vector访问元素时的速度会比deque快,这和两者内部实现有关

deque容器的实现原理

Deque 容器是连续的空间,至少逻辑上看来如此,连续现行空间总是令我们联想到 array数组 和vector,array 无法成长,vector 虽可成长,却只能向尾端成长,而且其成长其实是一个假象,事实上(1) 申请更大空间 2)原数据复制新空间 3)释放原空间 三步骤,如果不是 vector 每次配置新的空间时都留有余裕,其成长假象所带来的代价是非常昂贵的。
Deque 是由一段一段的定量的连续空间构成。一旦有必要在 deque 前端或者尾端增加新的空间,便配置一段连续定量的空间,串接在 deque 的头端或者尾端。Deque 最大的工作就是维护这些分段连续的内存空间的整体性的假象,并提供随机存取的接口,避开了重新配置空间,复制,释放的轮回,代价就是复杂的迭代器架构。既然 deque 是分段连续内存空间,那么就必须有中央控制,维持整体连续的假象,数据结构的设计及迭代器的前进后退操作颇为繁琐。Deque代码的实现远比vector或list 都多得多。Deque 采取一块所谓的 map(注意,不是 STL的 map 容器)作为主控,这里所谓的 map 是一小块连续的内存空间,其中每一个元素(此处成为一个结点)都是一个指针,指向另一段连续性内存空间,称作缓冲区。缓冲区才是deque的储存空间的主体

deque的api—构造函数

deque<T> deqT;//默认构造形式

deque(beg,end);//构造函数将[beg,end)区间中的元素拷贝给本身

deque(n,eLem);//构造函数将n 个eLem 拷贝给本身。

deque(const deque &deq);//拷贝构造函数。

void print(int a)
{
	cout << a << endl;
}

void test01()
{
	//构造
	deque<int> d1;
	d1.push_back(1);
	d1.push_back(2);
	d1.push_back(3);
	deque<int> d2(d1.begin(),d1.end());
	deque<int> d3(d1);
	deque<int> d4(10,8);
	//遍历
	for_each(d1.degin(),d1.end(),print);
}
deque的aip—赋值操作

assign(beg,end);//将[beg, end)区间中的数据拷贝赋值给本身。

assign(n,elem);//将n个elem拷贝赋值给本身。

deque& operator=(const deque &deq); //重载等号操作符

swap(deq);// 将deq与本身的元素互换

    deque<int> d3;
    deque<int> d4;

    d4.assign(d3);
    d4 = d3;
    
    d3.swap(d4);
    for_each(d4.begin(),d4.end(),print);

deque的api—容器的大小操作

deque.size();//返回容器中元素的个数

deque.empty();//判断容器是否为空

deque.resize(num);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器的元素被删除

deque.resizenum,elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置,如果容器变短,则末尾超出容器长的的元素被删除

#include <iostream>
#include <string.h>
#include <iterator>
#include <vector>
#include <string>
#include <algorithm>
#include <deque>
using namespace std;


void print(int a)
{
    cout << a << endl;
}

void test01()
{

    deque<int> d1;
    d1.push_back(1);
    d1.push_back(2);
    d1.push_back(3);
    cout << d1.size() << endl;
    if(!d1.empty())
    {
        cout << "不为空" << endl;
    }
    d1.resize(3);
    d1.resize(4,5);

    for_each(d1.begin(),d1.end(),print);

}

int main()
{
    test01();
    return 0;
}

编译运行

deque的api—双端的插入和删除

push_back(eLem);//在器尾部添加一个数据
push_front(eLem);//在容器头部插入一个数据
pop_back();//删除器最后一个数据
pop_front();//删除容器第一个数据

deque的api—数据存储

at(idx);//返回索引idx 所指的数据,如idx 越界,抛出out_of_range。
operator[];//返回索引dx 所指的数据,如idx 越界,不地出异,直接出错。
front();//返回第一个数据。
back();//返回最后一个数据

deque的api—插入操作

insert(pos,eLem);//在pos 位置插入一个eLem 元素的拷贝,返回新数据的位置。
insert(pos,n,elem);//在pos 位置插An 个eLem 数据,无返回值。
insert(pos,beg,end);//在pos 位置插入[beg,end)区间的数据,无返回值。

deque的api—删除操作

clear();//移除容器的所有数据

erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位智

erase(pos);//删除pos 位置的数据,返回下一个数据的位置。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1033885.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python函数绘图与高等代数互融实例(六): 条形图|直方图|饼状图

Python函数绘图与高等代数互融实例(一):正弦函数与余弦函数 Python函数绘图与高等代数互融实例(二):闪点函数 Python函数绘图与高等代数互融实例(三):设置X|Y轴|网格线 Python函数绘图与高等代数互融实例(四):设置X|Y轴参考线|参考区域 Python函数绘图与高等代数互融实例(五…

代码随想录刷题 Day 16

104.二叉树的最大深度 class Solution { public:int get_max(TreeNode* root) {if(root NULL) return 0;int left_depth get_max(root->left);int right_depth get_max(root->right);int depth max(left_depth, right_depth) 1;return depth;}int maxDepth(TreeNod…

Kafka的消息传递保证和一致性

前言 通过前面的文章&#xff0c;相信大家对Kafka有了一定的了解了&#xff0c;那接下来问题就来了&#xff0c;Kafka既然作为一个分布式的消息队列系统&#xff0c;那它会不会出现消息丢失或者重复消费的情况呢&#xff1f;今天咱们就来一探。 实现机制 Kafka采用了一系列机…

Node2Vec实战---《悲惨世界》人物图嵌入

1. pip各个包后导入 import networkx as nx # 图数据挖掘 import numpy as np # 数据分析 import random # 随机数# 数据可视化 import matplotlib.pyplot as plt %matplotlib inline plt.rcParams[font.sans-serif][SimHei] # 用来正常显示中文标签 plt.rcParams[axes.uni…

ArtifactResolveException

bug描述 Caused by: org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration$ArtifactResolveException: Could not resolve all files for configuration :app:debugCompileClasspath. 产生原因 一般可能是更换了新AndroidStudio导致的。依赖库未能成功…

关于Safari浏览器报错:Failed to load resource: 发生SSL错误,无法建立到该服务器的安全连接

报错信息&#xff1a; Failed to load resource: 发生SSL错误&#xff0c;无法建立到该服务器的安全连接 XMLHttpRequest cannot load https://xxxxxxx due to access control checks. 具体如图下&#xff1a; 原因是&#xff1a;页面上的http请求变了https请求 解决办法…

【校招VIP】产品思维创意之活动推广

考点介绍&#xff1a; 对于活动新手来说&#xff0c;策划出一个活动创意不是难事。但是如何把做活动考虑周详&#xff0c;理清运营活动的思路和流程&#xff0c;避免重复工作却是需要沉淀的。运营活动有一个很重要的思路方法&#xff0c;就是倒推。九维这次来和你们讲述倒推的思…

day31多线程01

1.实现多线程 1.1简单了解多线程【理解】 是指从软件或者硬件上实现多个线程并发执行的技术。 具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程&#xff0c;提升性能。 1.2并发和并行【理解】 并行&#xff1a;在同一时刻&#xff0c;有多个指令在多个CPU上…

大模型时代,探人工智能发展的新动向

导语 | 今年以来大模型的热度居高不下&#xff0c;人工智能成为国内外各大厂商争相布局的新赛道。那么近期 AI 领域有哪些值得关注的新趋势&#xff0c;它又将为软件开发带来哪些影响呢&#xff1f;今天&#xff0c;我们特邀了微智云科技 CEO、腾讯云 TVP 张虎老师&#xff0c;…

HR人才测评,什么是领导力?如何测评人的领导能力?

什么是领导力&#xff1f; 领导力指的是带领和组织团队&#xff0c;充分利用各种条件和资源&#xff0c;为团队目标而努力。具有卓越领导力的人&#xff0c;即使是在困难的条件下&#xff0c;也能充分利用条件&#xff0c;激励成员&#xff0c;提高团队的效率&#xff0c;朝着…

数据备份文件生成--根据表名生成对应的sql语句文件

最近客户有个需求&#xff0c;希望在后台增加手动备份功能&#xff0c;将数据导出下载保存。 当然&#xff0c;此方法不适用于海量数据的备份&#xff0c;这只适用于少量数据的sql备份。 这是我生成的sql文件&#xff0c;以及sql文件里的insert语句&#xff0c;已亲测&#x…

Software Grand Exposure: SGX Cache Attacks Are Practical【WOOT‘17】

目录 摘要引言我们的目标和贡献贡献新颖的SGX缓存攻击技术非加密应用程序泄漏对策分析 背景Intel SGX缓存结构性能监视计数器 系统和威胁模型对手的能力进攻目标 攻击设计PrimeProbePrimeProbe for SGX挑战 作者&#xff1a;Ferdinand Brasser, Urs M ̈uller, Alexandra Dmitr…

2023 第十二届中国智能产业高峰论坛 - 文档大模型的未来展望

目录 前言文档图像分析识别与理解中的技术挑战 文档图像分析识别与理解的研究主题文档图像分析与预处理文档解析与识别版面分析与还原文档信息抽取与理解AI安全知识化&存储检索和管理 多模态大模型在文档图像处理中的应用多模态的GPT-4在文档图像上的表现多模态的Google Ba…

Spring Security :二【原理解析、会话管理、RBAC中集成认证和授权、JWT】

文章目录 三、原理解析3.1 结构分析3.1 登录认证流程分析3.1.1 **UserDetailsService**3.1.2 自定义UserDetailsService3.1.3 **PasswordEncoder** 3.2 授权流程分析3.2.1 配置方式的原理解析3.2.2 注解方式原理解析 四、会话管理4.1 获取用户身份4.2 会话控制 五、 RBAC中集成…

swoole开发功能的消息队列与异步通信实现原理

随着互联网技术的迅猛发展&#xff0c;开发者对于高性能和高并发的需求也变得越来越迫切。作为一款开发框架&#xff0c;Swoole因其卓越的性能和丰富的功能而受到越来越多开发者的青睐。本文将介绍Swoole中消息队列和异步通信的实现原理&#xff0c;并结合代码示例进行详细说明…

远程桌面软件是否支持远程访问远程网络监控系统

远程桌面软件是一种通过网络连接&#xff0c;实现远程访问和控制计算机桌面的工具。它允许用户在自己的设备上操作远程计算机&#xff0c;就像直接坐在那台计算机前一样。然而&#xff0c;这种软件能否支持远程访问远程网络监控系统&#xff0c;取决于具体的软件以及目标网络监…

在React中,什么是组件的生命周期?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 挂载阶段&#xff08;Mounting&#xff09;⭐ 更新阶段&#xff08;Updating&#xff09;⭐ 卸载阶段&#xff08;Unmounting&#xff09;⭐ 错误处理阶段&#xff08;Error Handling&#xff09;⭐ 新的生命周期方法⭐ 写在最后 ⭐ 专栏…

初识Java 10-2 集合

目录 LinkedList Stack Queue Set Map 新特性&#xff1a;记录&#xff08;record&#xff09;类型 本笔记参考自&#xff1a; 《On Java 中文版》 LinkedList LinkedList同样实现了基本的List接口。相比于ArrayList&#xff0c;LinkedList拥有更快的插入和删除效率&…

华为云云耀云服务器L实例评测|Docker版的Minio安装 Springboot项目中的使用 结合vue进行图片的存取

前言 最近华为云云耀云服务器L实例上新&#xff0c;也搞了一台来玩&#xff0c;期间遇到过MySQL数据库被攻击的情况&#xff0c;Redis被攻击的情况&#xff0c;教训是密码不能太简单。在使用服务器时&#xff0c;学习到很多运维相关的知识。 本篇博客介绍如何在Linux中安装mi…

【数据结构】—交换排序之快速排序究极详解,手把手带你从简单的冒泡排序升级到排序的难点{快速排序}(含C语言实现)

食用指南&#xff1a;本文在有C基础的情况下食用更佳 &#x1f525;这就不得不推荐此专栏了&#xff1a;C语言 ♈️今日夜电波&#xff1a;靴の花火—ヨルシカ 0:28━━━━━━️&#x1f49f;──────── 5:03 …