C++STL 顺序容器操作总结(超级详细)

vector

vector 容器是 STL 中最常用的容器之一,它和 array 容器非常类似,都可以看做是对 C++普通数组的“升级版”。不同之处在于,array 实现的是静态数组(容量固定的数组),而 vector 实现的是一个动态数组,即可以进行元素的插入和删除,在此过程中,vector 会动态调整所占用的内存空间,整个过程无需人工干预。

vector尾部添加或移除元素非常快速。但是在中部或头部插入元素或移除元素比较费时


vector的构造函数

vector();
vector(initializer_list<_Ty> list);			//可以用聚合{}的方式初始化
vector(size_t size);						//指定vector初始大小
vector(size_t size, const Ty& val);			//指定大小,并把每个数据都设置为val
vector(Iter first, Iter last);				//以相同顺序复制[first,last)范围内的元素
vector(const vector& _Right);				//拷贝构造
vector(vector&& _Right);					//移动构造

代码示例:

/*
构造方式
*/
vector<int> a{ 1,2,3,4,5,6 };	//聚合初始化
const vector<int> b(5);	//指定大小
vector<int> c(10, 0);	//指定大小并且初始化为0
vector<int> d(a.begin(), a.end());	//复制另一个容器的数据
vector<int> e(a);		//拷贝构造
vector<int> f(b);

vector元素访问

Ty& operator[](size_t i);	//数组形式
Ty& at(size_t i);			//定位访问元素
Ty& front();				//返回头元素
Ty& back();					//返回尾部元素
Ty* data();					//返回指向数组中第一个元素的指针

代码示例:

cout << a[0] << endl;
cout << a.at(5) << endl;		//越界会出错
cout << a.front() << endl;	
cout << a.back() << endl;
auto p = a.data();	//返回指向数组第一个元素的指针  p=int*

vector容量相关

size_t size();								//获取vector有效元素个数
size_t max_size();							//可以存储的最大元素数量
size_t capacity();							//获取当前容量,自动扩容
void   reserve(size_t n);					//请求更改容量,如果n大于当前字符串的容量,则使容器将其容量增加到n个字符(或更大),小于可能不予理会(与实现有关)	
void   resize(size_t n);					//调整vector大小为n,n小于当前size,多余的数据会被丢掉
void   resize(size_t n,const Ty& val);		//如果n>size,剩下的用val填充
void   clear();								//清空数据,长度变为0
bool   empty();								//判断是否为空串,即size == 0
void   shrink_to_fit();						//请求vector减小其容量到合适大小

代码示例

cout << a.size() << endl;		//获取元素个数
cout << a.max_size() << endl;	//可以存储的最大元素个数
cout << a.capacity() << endl;	//获取当前容量个数,自动扩容
a.reserve(100);					//增大容量到100
cout << a.capacity() << endl;	//打印:100
a.resize(4);					//调整容量为4,多余的元素会被消除
a.resize(10, -99);				//调整容量为10,用-99做填充
a.clear();						//清空容器元素个数,但是它的总的容量不变
cout << a.size() << endl;		//打印:0   capacity:100
cout << a.empty() << endl;		//判断空容器
a.shrink_to_fit();				//将容器减小容量到适当的大小,当前元素个数0 即减小到0
cout << a.capacity() << endl;	//目前:0

vector修改元素

void push_back(const Ty& val);			//在尾部插入元素
void push_back(Ty&& val);				//同上
void emplace(Iter where,_Valty&& val);	//效率比较高
void emplace_back(_Valty&& val)
void pop_back();						//删除尾部元素

 void assign(const size_t size, const Ty& val);//设置新的大小,并用val设置所有值
 void assign(Iter First, Iter Last);		  //以相同顺序复制[first,last)范围内的元素
 void assign(initializer_list<_Ty> Ilist);	  //同时赋值多个元素
     
iter insert(iter _Where, const Ty& Val);	  //指定位置插入元素		
iter insert(iter _Where, const size_t Count, const Ty& val);//指定位置插入,并且可以指定插入数量
iter insert(iter _Where, Iter First, Iter Last);//指定位置插入[first,last)之间的元素
iter insert(iter _Where, initializer_list<_Ty> Ilist);

iterator erase(iter pos);						//删除pos指向的元素		
iterator erase(iter first,iterator last);		//删除[first,last)范围内的字符

void swap(vector& str);					//交换两个vector的内容

代码示例:

vector<int> temp{ 9,8,7,6,5,4 };
a.push_back(10);				//尾部插入元素10
a.pop_back();					//尾删
a.emplace(a.end(),10);			//emplace常用于类对象的构造,在a的末尾插入元素10
a.emplace_back(55);				//在尾部构造一个元素55
a.assign(50, -99);				//重新设置大小容器大小为50,并且用-99填充
a.assign(b.begin(), b.end());	//以相同的顺序复制b容器的数据

a.insert(a.begin(), 555);		//在容器的开始位置,插入一个元素555
a.insert(a.begin(), 10, 999);	//在a的begin处,插入10个999
a.insert(a.end(), temp.begin(), temp.end());	//在a的末尾处插入temp的指定范围的元素
a.insert(a.end(), { 1,2,3 });	//在容器的末尾插入一个聚合列表

a.erase(a.begin());				//删除容器的begin处的一个元素
a.erase(a.begin(), a.begin() + 9);//删除指定范围区一些元素
a.swap(temp);					//交换两个vector的内容

vector<int> null;
a.swap(null);					//利用swap实现清空容器

注意:

vector容器的操作没有对于头部的操作,因为vector是单端数组,对于头部的操作会导致后面一系列都发生变化,因此没有类似于pop_front和push_front的操作。


deque

deque是“double-ended queue”的缩写,和vector一样都是STL的容器,deque是双端数组,而vector是单端的。

deque在接口上和vector非常相似,在许多操作的地方可以直接替换。

  • deque 容器也擅长在序列尾部添加或删除元素(时间复杂度为O(1)),而不擅长在序列中间添加或删除元素。
  • deque 容器也可以根据需要修改自身的容量和大小。

和 vector 不同的是,deque 还擅长在序列头部添加或删除元素,所耗费的时间复杂度也为常数阶O(1)。并且更重要的一点是,deque 容器中存储元素并不能保证所有元素都存储到连续的内存空间中。


deque构造函数

deque();								//默认构造
deque(size_t count);					//指定size
deque(size_t count, Ty& val);			//批量构造
deque(const deque& right);				//拷贝构造
deque(deque&& right);					//移动构造
deque(Iter first,Iter last);			//区间构造

deque元素访问

Ty& operator[](size_t i);
Ty& at(size_t i);
Ty& front();
Ty& back();

deque容量相关

size_t size();								//获取有效元素个数
size_t max_size();							//可以存储的最大元素数量
void   resize(size_t n);					//调整大小为n,n小于当前size,多余的数据会被丢掉
void   resize(size_t n,const Ty& val);		//如果n>size,剩下的用val填充
void   clear();								//清空数据,长度变为0
bool   empty();								//判断是否为空串,即size == 0
void   shrink_to_fit();						//请求减小其容量到合适大小

deque的修改元素

void push_back(const Ty& val);			//在尾部插入元素
void push_back(Ty&& val);				//同上
void push_front(const Ty& val);			//在头部插入元素
void push_front(Ty&& val);				//同上

void emplace(Iter where,_Valty&& val);	//效率比较高
void emplace_back(_Valty&& val);
void emplace_front(_Valty&& val)
void pop_back();						//删除尾部元素

 void assign(const size_t size, const Ty& val);//设置新的大小,并用val设置所有值
 void assign(Iter First, Iter Last);		  //以相同顺序复制[first,last)范围内的元素
 void assign(initializer_list<_Ty> Ilist);	  //同时赋值多个元素
     
iter insert(iter _Where, const Ty& Val);	  //指定位置插入元素		
iter insert(iter _Where, const size_t Count, const Ty& val);//指定位置插入,并且可以指定插入数量
iter insert(iter _Where, Iter First, Iter Last);//指定位置插入[first,last)之间的元素
iter insert(iter _Where, initializer_list<_Ty> Ilist);

iterator erase(iter pos);						//删除pos指向的元素		
iterator erase(iter first,iterator last);		//删除[first,last)范围内的字符

void swap(vector& str);					//交换两个vector的内容

注意:deque的操作跟vector的操作基本一致,只不过deque是双端数组,因此对于头尾的操作速度都可以,因此它支持对头部的操作,如pop_front和push_front


list

list 容器,又称双向链表容器,即该容器的底层是以双向链表的形式实现的。这意味着,list 容器中的元素可以分散存储在内存空间里,而不是必须存储在一整块连续的内存空间中。

list构造函数

list();
list(size_t count);
list(size_t count,const Ty& val);
list(const list& right);
list(list&& right);
list(Iter first,Iter last);

代码示例:

list<int> a{ 1,2,3,4,5,6,7,8,9 };
list<int> b(a.begin(), a.end());
list<int> c(10);
list<int> d(10,-999);

list元素访问

Ty& front();
Ty& back();

list容量相关

bool empty();
size_t size();
size_t max_size();							//获取最大能够容纳的数量
void   resize(size_t n);					//调整大小为n,n小于当前size,多余的数据会被丢掉
void   resize(size_t n,const Ty& val);		//如果n>size,剩下的用val填充

list添加元素

void push_back(Ty& val);
void push_front(Ty& val);
void emplace_back(Args&&... args);
void emplace_front(Args&&... args);
Iter emplace(Iter pos,Args&&...args);

void assign(const size_t size, const Ty& val);//设置新的大小,并用val设置所有值
void assign(Iter First, Iter Last);		  //以相同顺序复制[first,last)范围内的元素
void assign(initializer_list<_Ty> Ilist);	  //同时赋值多个元素

iter insert(iter _Where, const Ty& Val);	  //指定位置插入元素
iter insert(iter _Where, Ty&& Val);	  		  //指定位置插入元素	
iter insert(iter _Where, const size_t Count, const Ty& val);//指定位置插入,并且可以指定插入数量
iter insert(iter _Where, Iter First, Iter Last);//指定位置插入[first,last)之间的元素
iter insert(iter _Where, initializer_list<_Ty> Ilist);

list删除元素

iterator erase(iter pos);						//删除pos指向的元素		
iterator erase(iter first,iterator last);		//删除[first,last)范围内的字符

void pop_front();
void pop_back();
void clear();

list的其他操作

//list拼接,x中的元素会被直接转移到当前list中,不会涉及元素的构造
void splice (Iter where, list& x);	//把x插入到where位置,x会被清空
void splice (Iter where, list& x, Iter first);//把x的first位置的元素,插入到list的where位置
void splice (Iter where, list& x,Iter first, Iter last);//把x的[first,last)位置的元素,插入到list的where位置
void remove(const Ty& val);	//删除所有等于val的元素。这将调用这些对象的析构函数,并通过删除元素的数量来减少容器的大小。erase按元素的位置(使用迭代器)删除元素
template<typename Predicate>
void remove_if(Predicate pred);	//从容器中删除所有谓词pred返回true的元素。
void unique();	//从容器中每个相等元素的连续组中除去除第一个元素外的所有元素。
template <class Predicate>
void unique(Predicate _Pred);//以确定元素“唯一性”的特定比较函数作为参数。实际上,可以实现任何行为(并且不仅可以进行相等比较),从第二个开始)并删除如果谓词返回true,则从列表中返回i。
void merge(list& right);	//合并两个链表,如果两个链表都有序,合并之后同样也是有序的,否则合并失败,程序中断
void sort();				//对list元素进行排序,默认是升序
void sort(Predicate _Pred);	//可以自己修改排序规则
void reverse();				//反转list

代码示例:

class Foo{		//用于比较的仿函数
public:
	bool operator()(const int& data){
		return data % 2 != 0;
	}
};
list<int> temp{1,2,3,4,5,6};
list<int> temp2(temp);
a.splice(a.begin(),temp);		//把temp容器插入到a指定的位置,temp容器会被清空!
//list的迭代器不具有+-等操作
a.splice(a.begin(), temp2, --temp2.end());	//将temp2容器的指定位置元素插入到a的指定位置位置
/*
remove函数详解
*/
//删除所有等于val的值的元素
a.remove(6);		
//remove_if 删除所有谓词pred中返回true的元素
//利用lamdba表达式,删除所有偶数元素
a.remove_if([&](const int& data) {return data % 2 == 0; });	
//利用仿函数删除奇数
a.remove_if(Foo());		
//利用参数绑定,删除所有等于5的元素
auto NotEqual = bind(equal_to<int>(), placeholders::_1, 5);	
a.remove_if(NotEqual);

list<int> unq{ 1,1,2,3,3,4,4,5,6,6,7,8,8 };
//unq.unique();			//去重,删除相邻的重复元素
//unique算法 配合erase删除后面的元素
auto it=unique(unq.begin(), unq.end(),bind(equal_to<int>(),placeholders::_1,placeholders::_2));
//unq: 1,2,3,4,5,6,7,8,6,6,7,8,8
unq.erase(it, unq.end());	
//unq:1,2,3,4,5,6,7,8

a.sort(less<>());
unq.merge(a);		//合并两个链表,不是有序递增的则会终止
unq.sort();
unq.reverse();

forward_list

forward_list构造函数

forward_list();
forward_list(size_t count);
forward_list(size_t count,const Ty& val);
forward_list(const list& right);
forward_list(list&& right);
forward_list(Iter first,Iter last);

forward_list迭代器

Iter before_begin();		//返回第一个元素的前一个位置,禁止解引用

forward_list元素访问

Ty& front();

forward_list容量相关

bool empty();
size_t max_size();

forward_list添加元素

void push_front(Ty& val);
void emplace_front(Args&&... args);
Iter emplace_after(Iter where,Args&&...args);	//在where的下一个位置处插入新元素

void assign(const size_t size, const Ty& val);//设置新的大小,并用val设置所有值
void assign(Iter First, Iter Last);		  //以相同顺序复制[first,last)范围内的元素
void assign(initializer_list<_Ty> Ilist);	  //同时赋值多个元素

iter insert_after(iter _Where, const Ty& Val);	  //where下一个位置插入元素
iter insert_after(iter _Where, const size_t Count, const Ty& val);//where下一个位置插入,并且可以指定插入数量
iter insert_after(iter _Where, Iter First, Iter Last);//where下一个位置插入[first,last)之间的元素
iter insert_after(iter _Where, initializer_list<_Ty> Ilist);

forward_list删除元素

iterator erase_after(iter where);		//删除where下一个位置的元素
iterator erase_after(iter first,iterator last);		//删除(first,last)范围内的字符

void pop_front();				//删除头部元素

void clear();					//清空链表

forward_list的其他操作

//list拼接,x中的元素会被直接转移到当前list中,不会涉及元素的构造
void splice (Iter where, list& x);		//把x插入到where下一个位置
void splice (Iter where, list& x, Iter first);//把x的first的下一个位置的元素,插入到list的where下一个位置
void splice (Iter where, list& x,Iter first, Iter last);//把x的(first,last)位置的元素,插入到list的where位置

void remove(const Ty& val);	//删除所有等于val的元素。
template<typename Predicate>
void remove_if(Predicate pred);	//从容器中删除所有谓词pred返回true的元素。
void unique();	//从容器中每个相等元素的连续组中除去除第一个元素外的所有元素。
template <class Predicate>
void unique(Predicate _Pred);//以确定元素“唯一性”的特定比较函数作为参数。实际上,可以实现任何行为(并且不仅可以进行相等比较),从第二个开始)并删除如果谓词返回true,则从列表中返回i。


void merge(list& right);	//合并两个链表,如果两个链表都有序,合并之后同样也是有序的,否则合并失败,程序中断
void sort();				//对list元素进行排序,默认是升序
void sort(Predicate _Pred);	//可以自己修改排序规则
void reverse();				//反转list

string

string是STL的字符串类型,通常用来表示字符串。而在使用string之前,字符串通常是用char表示的。string与char都可以用来表示字符串,那么二者有什么区别呢。

string和char*的比较

  • string是一个类, char*是一个指向字符的指针。

    string封装了char*,管理这个字符串,是一个char*型的容器

  • string不用考虑内存释放和越界。

    string管理char所分配的内存。每一次string的复制,取值都由string类负责维护,不用担心复制越界和取值越界等。

  • string提供了一系列的字符串操作函数(这个等下会详讲)

    查找find,拷贝copy,删除erase,替换replace,插入insert

string的构造函数

string();									//默认构造
string(const char* ptr);					//char*指向的字符串
string(const string& right);				//拷贝构造
string(string&& right);						//移动构造
string(iter first,iter last);				//以相同顺序复制[first,last)范围内的字符
string(const size_t count,const char c);	//生成count个由字符c组成的序列
string(const char *ptr,size_t count);		//char*指向的字符串,前count个字符

string的存取字符操作

ostream& operator<<(ostream& out,string& right);	//直接输出string
char& operator[](size_t off);						//获取off下标的字符(相对于首地址的偏移)
char& at(size_t off);								//同上  但是越界会抛异常
char& front();										//获取头部元素
char& back();										//获取尾部元素

string容量相关

size_t size();								//获取字符串长度
size_t length();							//同上
size_t max_size();							//字符串可以存储的最大长度
size_t capacity();							//获取string内部存储字符串的内存大小,自动扩容
void   reserve(size_t n);					//请求更改容量,如果n大于当前字符串的容量,则使容器将其容量增加到n个字符(或更大),小于可能不予理会(与实现有关)	
void   resize(size_t n,char c = '\0');		//调整字符串大小, 如果n小于当前字符串长度,则当前值将缩短为它的前n个字符,并删除第n个字符之外的字符。 如果n大于当前字符串的长度,则以c进行填充多余空间。
void   clear();								//清空字符串,长度变为0
bool   empty();								//判断是否为空串,即size == 0
void   shrink_to_fit();						//请求sting减小其容量到合适大小(可能不予理会)

string修改

string& operator+=(string& right);
string& operator+=(char * str);
string& operator+=(char c);
//append
string& append(string& right);
string& append(string& right,size_t pos,size_t sublen = npos);	//从right pos位置开始,复制sublen长度到this
string& append(char *str);
string& append(char *str,size_t n);		//把str的前n个追加到当前string
string& append(size_t n,char c);		//追加n个字符c
string& append(iter first,iter last);	//以相同顺序追加[first,last)范围内的字符

void push_back(char c);					//追加字符c
//和构造函数差不多
string& assign(...);					//为字符串分配一个新值,替换其当前内容
//和append差不多,只是多了个插入位置
string& insert(size_t pos,string& str);	//将str插入到pos所指示的字符之前

string& erase(size_t pos = 0,size_t len = npos);	//删除从pos开始跨越len个字符的部分
iterator erase(iter p);						//删除p指向的字符		
iterator erase(iter first,iterator last);	//删除[first,last)范围内的字符


string& replace(size_t pos,size_t len,string &str);
string& replace(iter i1, iter i2, const string& str);	
string& replace(size_t pos,  size_t len,  const string& str,
                size_t subpos, size_t sublen);
string& replace(size_t pos,  size_t len,  const char* s);
string& replace(size_t pos,  size_t len,  const char* s, size_t n);
string& replace(iter i1, iter i2, const char* s, size_t n);
string& replace(size_t pos,  size_t len,  size_t n, char c);
string& replace(iter i1, iter i2, size_t n, char c);

template <class Inputiter>
string& replace (iter i1, iter i2,Inputiter first, Inputiter last);


void swap(string& str);					//交换两个string的内容
void swap(string& left,string& right);	//全局重载

void pop_back();						//删除最后一个字符

string操作

const char* c_str();			//获取c风格字符串
const char* data();				//同上
size_t copy(char* s,size_t len,size_t pos = 0);//把当前串中以pos开始的len个字符拷贝到以s为起始位置的字符数组中,返回实际拷贝的数目。注意要保证s所指向的空间足够大以容纳当前字符串,不然会越界。

//find:返回查找到的起始下标,找不到返回string::npos
size_t find(const string& str, size_t pos = 0);	//从pos位置开始查找str
size_t find(const char* s, size_t pos = 0);	//从pos位置开始查找s
size_t find(const char* s, size_t pos, size_t n);//把s中的前n个字符,在string中的pos位置开始查找
size_t find(char c, size_t pos = 0);	//从pos位置开始查找字符c
size_t rfind(...);						//同上,只不过是反向查找
size_t find_first_of(...);				//查找与参数中字符串任意一个字符匹配的第一个字符
size_t find_last_of(...);				//同上,反向查找
size_t find_first_of(...);				//查找与参数中字符串任意一个字符都不匹配的第一个字符
size_t find_last_of(...);				//同上,反向查找
string substr(size_t pos=0,size_t len=npos);//返回一个新构造的string对象,其值初始化为该对象的子字符串的副本。

string静态成员

  • npos是一个静态成员常量值,被定义为-1,但是size_t是unsigned int,值是最大值(4294967295)
  • 用作字符串成员函数中len(或sublen)参数的值时,此值表示*“直到字符串结尾”*。
  • 作为返回值,通常用于表示没有匹配项。
posted @ 2022-09-28 14:36  hugeYlh  阅读(102)  评论(0编辑  收藏  举报  来源