c++STL概述
目录
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 2v2.push_back(i+10);//v2尾部插入 10 11 12v3.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;//输出ostr[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());//1234000000vector<int> v2;v2.reserve(1000);//为v2预留1000个空间 设置容量cout << v2.size() << endl;//0cout << 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;//3cout << v1[2] << endl;//3cout << v1.front() << endl;//1cout << 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 1024v1.resize(10);//cout << v1.size()<< " " << v1.capacity() << endl;//10 1024vector<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 位置的数据,返回下一个数据的位置。
相关文章:
c++STL概述
目录 STL基本概念 STL六大组件 STL的优点 STL三大组件 容器 算法 迭代器 普通的迭代器访问vector容器元素 算法for_each实现循环 迭代器指向的元素类型是自定义数据类型 迭代器指向容器 常用容器 string容器 string的基本概念 string容器的操作 string的构造函…...
利用容器技术优化DevOps流程
利用容器技术优化DevOps流程 随着云计算的快速发展,容器技术也日益流行。容器技术可以打包和分发应用程序,并实现快速部署和扩展。在DevOps流程中,容器技术可以大大优化开发、测试、部署和运维各个环节。本文将介绍如何利用容器技术优化DevO…...
91 # 实现 express 的优化处理
上一节实现 express 的请求处理,这一节来进行实现 express 的优化处理 让 layer 提供 match 方法去匹配 pathname,方便拓展让 layer 提供 handle_request 方法,方便拓展利用第三方库 methods 批量生成方法性能优化问题 进行路由懒加载&#…...
arcgis拓扑检查实现多个矢量数据之间消除重叠区域
目录 环境介绍: 操作任务: 步骤: 1、数据库和文件结构准备 2、建立拓扑规则 3、一直下一页默认参数后,进行拓扑检查 4、打开TP_CK_Topology,会自动带出拓扑要素,红色区域为拓扑错误的地方࿱…...
基于Vue+ELement搭建登陆注册页面实现后端交互
🎉🎉欢迎来到我的CSDN主页!🎉🎉 🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚 🌟推荐给大家我的专栏《ELement》。🎯🎯 …...
JS获取经纬度, 并根据经纬度得到城市信息
在JavaScript中,获取经纬度通常需要使用定位服务,比如HTML5的Geolocation API。然而拿到坐标后,将经纬度转换为城市信息,则需要使用逆地理编码服务接口,比如百度或者高德的 API, 但是他们收费都很高, 我们可以使用一些…...
mac m1 docker安装nacos
文章目录 引言I m1安装docker1.1 Docker 下载1.2 终端Docker相关命令II docker安装nacos2.1 安装nacos2.2 镜像启动see alsoMac 查看进程端口引言 使用docker方式安装是最方便的 I m1安装docker 1.1 Docker 下载 https://docs.docker.com/docker-for-mac/apple-silicon/点击…...
位段 联合体 枚举
Hello好久不见,今天分享的是接上次结构体没有分享完的内容,这次我们讲讲位段 枚举和联合体的概念以及他们的用法。 2.1 什么是位段 位段的声明和结构是类似的,有两个不同: 1.位段的成员必须是 int、unsigned int 或signed int 。 …...
PHP循环获取Excel表头字母A-Z,当超过时输出AA,AB,AC,AD······
PHP循环获取Excel表头字母A-Z,当超过时输出AA,AB,AC,AD PHP循环生成Excel的列字母表 $count_num 26 * 27; $letter A; $arr []; while($count_num--){$arr[] $letter;$letter; }结果如下: 转为JSON更为直观: ["A","B&…...
识别准确率达 95%,华能东方电厂财务机器人实践探索
摘 要:基于华能集团公司大数据与人工智能构想理念,结合东方电厂实际工作需要,财务工作要向数字化、智能化纵深推进,随着财务数字化转型和升级加速,信息化水平不断提升,以及内部信息互联互通不断加深&#x…...
代码随想录算法训练营 单调栈part03
一、柱状图中最大的矩形 84. 柱状图中最大的矩形 - 力扣(LeetCode) 单调栈很重要的性质,就是单调栈里的顺序,是从小到大还是从大到小。 栈顶和栈顶的下一个元素以及要入栈的三个元素组成了我们要求最大面积的高度和宽度&#x…...
使用 MyBatisPlus 的注解方式进行 SQL 查询,它结合了条件构造器(Wrapper)和自定义 SQL 片段来构建查询语句。
MyBatis-Plus 是一个基于 MyBatis 的增强工具,它提供了一套方便的注解方式来进行 SQL 查询。其中,它结合了条件构造器(Wrapper)和自定义 SQL 片段来构建查询语句。 官网:条件构造器 | MyBatis-Plus 1、使用 Wrapper …...
Python中统计单词出现的次数,包含(PySpark方法)
思路: 定义一个函数,使用open函数,将文本内容打开。 定义一个空字典和空列表,进行循环及条件判断操作def count_word(file_path):dict_data {} #定义一个空字典f open(file_path,"r",encoding"UTF-8")lis…...
探讨基于IEC61499 的分布式 ISA Batch 控制系统
ISA SP88 是批次过程控制的标准,对应的IEC标准是IEC 61512。该标准中一个重要的部分是配方管理(Recipe Management)。 所谓配方,是根据批量产品的要求,材料设定加工工艺,加工流程和参数。类似于传统制造业的…...
图论16(Leetcode863.二叉树中所有距离为K的结点)
答案: /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val x; }* }*/ class Solution {public List<Integer> distanceK(TreeNode root, TreeNode tar…...
【小沐学C++】C++ MFC中嵌入64位ActiveX控件(VS2017)
文章目录 1、简介1.1 MFC1.2 ActiveX 2、VS2017添加ActiveX控件结语 1、简介 1.1 MFC Microsoft 基础类 (MFC) 库针对大部分 Win32 和 COM API 提供面向对象的包装器。 虽然此包装器可用于创建极为简单的桌面应用程序,但当你需要开发具有多个控件的更复杂的用户界…...
Linux常用命令—find命令大全
文章目录 一、find命令常用功能1、find命令的基本信息如下。2、按照文件名搜索3、按照文件大小搜索4、按照修改时间搜索5、按照权限搜索举例:6、按照所有者和所属组搜索7、按照文件类型搜索8、逻辑运算符 一、find命令常用功能 1、find命令的基本信息如下。 命令名…...
form组件的封装(element ui ) 简单版本
当你使用Vue.js构建Web应用时,封装可复用组件是提高开发效率和代码可维护性的关键之一。在这篇文章中,我们将探讨如何使用Vue.js来创建一个通用的表单组件,以及如何将它封装成一个可配置的组件。 实现思路 拿下表单模板一个个的改造&#x…...
树形DP杂题
引 对老师布置的题目稍微记录一下吧 也算对树形 D P DP DP 的巩固 T1 Ostap and Tree 题目传送门 由于有 距离 k 距离k 距离k 的限制,设计二维 d p dp dp 设计状态: f i , j : i 的子树内,离 i 最近的染色点与 i 距离为 j 且若 j <…...
Webpack使用plugin插件自动在打包目录生成html文件
我们使用html-webpack-plugin插件可以自动在打包代码目录生成html文件 使用步骤: 一、安装依赖 在控制台中输入如下代码: npm i -D html-webpack-plugin 二、在webpack.config.js中配置插件 const HTMLPlugin require("html-webpack-plugin&q…...
图像处理与计算机视觉--第一章-计算机视觉简介-10问
第一章-计算机视觉简介-10问 1.CV与AI的关系是什么? CV(Computer Vision)是Al的子领域,它致力于使计算机能够理解和解释图像和数据,CV借助AI技术,比如深度学习/机器学习,实现目标识别,分析和处理任务。AI提供了CV所需要的算法…...
LeetCode 80. 删除有序数组中的重复项 II
文章目录 一、题目二、Java 题解 一、题目 给你一个有序数组 nums,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用…...
【前端面试题】浏览器面试题
文章目录 前言一、浏览器面试问题1.cookie sessionStorage localStorage 区别2.如何写一个会过期的localStorage,说说想法2.如何定时删除localstorage数据2.localStorage 能跨域吗2.memory cache 如何开启2.localstorage的限制2.浏览器输入URL发生了什么2.浏览器如何…...
PHP 生成 PDF文件
参考官网 Example 009 : Image() TCPDF laravel 可以使用 composer 安装 tecnickcom/tcpdf 进行使用 //require_once("../app/Extend/tcpdf/tcpdf.php"); $pdf new TCPDF();// 设置文档信息$pdf->SetCreator(懒人开发网);$pdf->SetAuthor(懒人开发网);$…...
讲讲项目里的仪表盘编辑器(一)
需求 要做一个仪表盘系统,要求有: ① 设计功能(包括布局、大小、排列) ② 预览功能 ③ 运行功能 布局选择 做编辑器,肯定要先选择布局。 前端有几种常用布局。 静态布局 也叫文档布局。默认的网页形式…...
解决方案 | 如何构建市政综合管廊安全运行监测系统?
如何构建市政综合管廊安全运行监测系统?WITBEE万宾城市生命线智能监测仪器,5年免维护设计,集成10多项结构与气体健康监测指标,毫秒级快速响应,时刻感知综合管廊运行态势...
JCEF中js与java交互、js与java相互调用
jcef中js与java相互调用,java与js相互调用,chrome与java相互调用,java与chrome相互调用、jcef与java相互调用 前提:https://blog.csdn.net/weixin_44480167/article/details/133170970(java内嵌浏览器CEF-JAVA、jcef、…...
9.20 校招 实习 内推 面经
绿泡*泡: neituijunsir 交流裙 ,内推/实习/校招汇总表格 1、校招丨智行者2024年校园招聘正式启动啦 校招丨智行者2024年校园招聘正式启动啦 2、校招 | 乐动机器人2024校园招聘 校招 | 乐动机器人2024校园招聘 3、校招丨小天才2024届秋季校园招聘 …...
基于JAVA+SpringBoot+Vue+协同过滤算法+爬虫的前后端分离的租房系统
✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取项目下载方式🍅 一、项目背景介绍: 随着城市化进程的加快…...
【Android Framework系列】第16章 存储访问框架 (SAF)
1 概述 Android 4.4(API 级别 19)引入了存储访问框架 (Storage Access Framework)。SAF让用户能够在其所有首选文档存储提供程序中方便地浏览并打开文档、图像以及其他文件。 用户可以通过易用的标准 UI,以统一方式在所有应用和提供程序中浏…...
wordpress 插入pdf/快速排名优化公司
第一次接触王老师的大数据课程是在2014年底,当时在51CTO上有了spark六阶段,当时真的太吸引我了,但是由于是学生,所以没那么多钱去买教程,真的太后悔了,但是呢!后来看到了《大数据不眠夜…...
学校网站怎么建设/想学销售去哪培训
气候类 1、北京日均最低气温 var bj_temp_ low [-6,-4,3,10,16,21,24,23,17,9,1,-5]2、北京日均最高气温 var bj_temp_ hight [3,6,15,23,29,32,33,32,27,19,10,4]3、北京历史最高气温 var bj_temp_ max [24,19,29,34,38,38,39,36,32,28,24,28]4、北京历史最低气温 var …...
在线网站制作平台/广告平台有哪些
平台无关: 在一个计算机上编译得到的字节码文件可以复制到任何一个安装了Java运行环境的计算机上直接使用。字节码由Java虚拟机负责解释运行,即Java虚拟机负责将字节码翻译成本地计算机的机器码,并将机器码交给本地的操作系统来运行。 Java…...
上海网站建设怎么弄/临沂seo代理商
8种机械键盘轴体对比本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?一、HMR介绍在我们开发react应用的时候,在配置了webpack-dev-server的前提下每一次的组件内容修改都需要手动的刷新浏览器,为了解决这个问题…...
威海城乡建设局网站首页/百度下载安装到桌面
Redmine的code review插件可以显示代码的具体内容,但是缺少代码的作者、发布时间等等信息,所以需要对插件进行修改,添加这个功能。如图所示为没有修改时的显示页面: 可以看到,图中只有代码。 我们要做的就是在上面添加…...
天安节能科技园公司做网站/最新实时新闻
给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。 元素的顺序可以改变。你不需要考虑数组中超出新…...