【2024.1.12】C++STL容器常用方法

目录

Vector

1.构造函数

2.数据操作函数

3.判断函数

4.Vector迭代器的失效

List

1.头尾函数

2.反向迭代器

3.List迭代器的失效

Deque

Stack

1.构造函数

2.出栈、入栈、访问栈顶函数

3.判断函数

Queue

1.出队、入队、访问队首/队尾函数

2.其他函数

Set

1.插入与遍历函数

2.删除函数

3.查找函数

4.利用伪函数自定义排序规则

Map

1.插入、遍历函数

2.获取键对应的值


Vector

1.构造函数

#include <vector>
//直接通过数组创建一个vector
vector<int> vecA = {1, 2, 3, 4};

//复制迭代器区间内的元素到vector中
vector<int> vecB(vecA.begin(), vecA.end());

//复制另一个数组的元素到vector中
int Array[4] = {1, 2, 3, 4};
vector<int> vecC(Array, Array+4);

//复制构造函数
vector<int> vecD(vecA);
/*或vecD = vecA;*/

//创建一个vector,元素个数为3,且值均为6
vector<int> vecE(3, 6);

2.数据操作函数

#include <vector> 
vector<int> vecA;
//向量中迭代器指向元素前增加一个元素x
vecA.insert(vecA.begin()+3, x);
/*insert函数有三种插入方法:
insert(pos_iterator,elem):向量中迭代器指向元素位置前增加一个元素elem
insert(pos_iterator,n,elem):向量中迭代器指向元素前增加n个相同的元素elem
insert(pos_iterator,first_iterator,last_iterator):
向量中迭代器指向元素前插入另一个相同类型向量的[first,last)间的数据*/

//删除向量中迭代器指向元素
vecA.erase(vecA.begin()+3);

//返回向量第i个元素(i=0开始)
cout<<vecA.at(i);

//设置向量中前4个元素的值为10(assgin函数是覆盖式的)
vecA.assign(4,10);

//向量中[first,last)中元素设置成当前向量元素
vecB.assign(vecA.begin()+3,vecA.end()-2);

//交换两个同类型向量的数据
vecB.swap(vecA);

//重新指定容器的长度为num,若容器变长,则用elem填充新位置
vecC.resize(num,elem);


3.判断函数


//判断向量是否为空,返回值为布尔类型
vecA.empty();
//返回向量中元素的个数
vecA.size();
//清空向量中所有元素
vecA.clear();

4.Vector迭代器的失效

动态数组在进行插入操作后,可能会触发容器的扩容,导致数组中的元素被重新存储到新的连续内存空间,迭代器失效。insert()函数的返回值即为指向所插入元素的迭代器,所以可以使用语句it = list.insert(it)来立即给失效的迭代器重新赋值。

同理,动态数组的元素删除后会使迭代器的指针变为野指针,所以需要给迭代器重新赋值,erase()函数的返回值即为删除元素下一个元素的迭代器,所以可以使用语句it = list.erase(it)来立即给失效的迭代器重新赋值。


List

List容器中大多函数和Vector容器相同,都有.begin()/.end()迭代器、数值操作函数、构造函数等,但由于双向链表的特殊结构,没有at函数与[ ]操作符,迭代器只能++逐一递增,但链表拥有反向迭代器:reverse_iterator。(vector也有)

1.头尾函数

#include <list>
list<int> li;
//头插法&尾插法&头删法&尾删法
li.push_front(8);
li.push_back();
li.pop_front();
li.pop_back();

//获取、修改头尾结点
li.front() = 1;
li.back() = 3;

2.反向迭代器

rbegin是倒数第一个,rend是倒数第一个的前一个。

使用.reverse();函数也能实现list容器的反转。

list<int> li = { 1,2,3,4,5,6 };
list<int>::reverse_iterator it;
for (it = li.rbegin(); it != li.rend(); it++) {
    cout << *it << endl;
}

3.List迭代器的失效

由于链表的结点删除后会使迭代器的指针变为野指针,所以需要给迭代器重新赋值,erase()函数的返回值即为删除结点下一个结点的迭代器,所以可以使用语句it = list.erase(it)来立即给失效的迭代器重新赋值。

但是由于链表插入操作不会影响当前结点的空间,因此List容器的insert()函数并不会导致迭代器失效。


Deque

deque容器和vector容器基本一致,但拥有头元素操作函数:pop_front()函数和push_front()函数。deque容器在头部和尾部进行元素的添加和删除都是O(1),不像vector容器对头部进行操作的时间复杂度为O(n)。


Stack

stack容器的元素遵循先进后出的原则,容器中的函数十分有限,且没有对应的迭代器。(栈不允许遍历)

1.构造函数

stack<int> A;
//利用构造函数将A容器中元素拷贝到B、C中
stack<int> B(A);
stack<int> C = A;

2.出栈、入栈、访问栈顶函数

#include <iostream>
#include <stack>

using namespace std;
int main()
{
    stack<int> stk;
    stk.push(1);
    stk.push(2);
    stk.push(3);
    stk.push(4);
//入栈操作
    stk.pop();
//栈顶元素出栈
    cout << stk.top() << endl;
//返回栈顶元素,结果为3
    return 0;
}

3.判断函数

由于栈为空时调用pop函数会导致运行出错,需要判断栈是否已经为空。

stack<int> A;
//判断堆栈是否为空
A.empty();

//返回容器存储元素个数
A.size();

Queue

Queue容器的元素遵循先进后出的原则,队尾插入元素,队首取出元素。队列容器也没有对应的迭代器,无法进行遍历操作。

1.出队、入队、访问队首/队尾函数

#include <iostream>
#include <queue>

using namespace std;
int main()
{
    queue<int> Q;
    Q.push(1);
    Q.push(2);
    Q.push(3);
    Q.push(4);
//在队尾插入元素
    Q.pop();
//在队首删除元素
if(!Q.empty())//判断队列非空
    cout << Q.front() << endl << Q.back() << endl;
//分别在首尾访问元素,结果为2和4
    return 0;
}

2.其他函数

队列容器和栈容器一样,也有empty(),size()判断函数以及构造函数,也可以让stack.front()或back()充当左值,给队首或队尾元素重新赋值。


Set

Set集合的特点:元素有序、不重复、无索引;

MultiSet集合的特点:元素有序、可重复、无索引;

Set是一个集合容器,集合中的元素自动按顺序排列,因此不能指定插入位置。Set采用红黑树变体的数据结构实现,插入和删除操作效率高于Vector容器。不能直接修改集合中的元素值,必须删除指定元素后插入要替代的元素。

Set容器和之前的容器相似,也可以用拷贝构造函数以及swap()函数进行容器内元素的交换。

1.插入与遍历函数

#include <iostream>
#include <set>

using namespace std;
int main()
{
    set<int> A;
    A.insert(1);
    A.insert(4);
    A.insert(2);
    A.insert(3);
    A.insert(5);
    A.insert(5);
    A.insert(3);
//set容器默认为升序排序
    set<int>::iterator it;
    for (it = A.begin(); it != A.end(); it++) {
        cout<<*it<<endl;
    }
//遍历结果为1,2,3,4,5
    return 0;
}

set容器默认为升序排序,可以使用反向迭代器从大到小遍历,或者使用set<int, greater<int>>构造容器。


2.删除函数

Set无法进行指定位置的插入;和Vector容器与List容器相似,Set容器在函数中传递迭代器的参数完成指定位置的删除。(函数参数中不能使用反向迭代器)

//清除所有元素
set.clear();

//删除迭代器所指向元素,返回下一个元素的迭代器
set.erase(pos_iterator);

//删除迭代器中值为elem的元素(不存在则返回false)
set.erase(elem);

//删除迭代器指向区间[first,last)间的数据
set.erase(first_iterator,last_iterator);

3.查找函数

#include <iostream>
#include <set>
using namespace std;

int main()
{
    multiset<int> A;
    A.insert(1);
    A.insert(4);
    A.insert(2);
    A.insert(3);
    A.insert(5);
    A.insert(5);
    A.insert(3);
    /*1,2,3,3,4,5,5*/
    cout << *A.find(3) << endl;
//find(elem)返回第一个指向elem的迭代器,结果为3

    cout << A.count(3) << endl;
//count(elem)返回容器中elem的个数,结果为2

    cout << *A.lower_bound(3) << endl;
//lower_bound(elem)返回第一个>=elem的迭代器,结果为3

    cout << *A.upper_bound(3) << endl;
//upper_bound(elem)返回第一个>elem的迭代器,结果为4


    pair<multiset<int>::iterator, multiset<int>::iterator> P = A.equal_range(3);
    cout<< *(P.first) <<endl;
//.equal_range(elem)返回两个迭代器,分别是lower_bound(elem)和upper_bound(elem)的结果
//结果为3  4
    return 0;
}

其中pair<T1,T2>为对组,可以同时存储两种类型的数据,使用.first/.second获取成员。


4.利用伪函数自定义排序规则

#include <iostream>
#include <set>

using namespace std;
class shishishi {
public :
    bool operator()(int a, int b)const{//第一个空括号表示对函数()运算符的重载
//改成这行VS会报错:bool operator()(const int &a, const int &b) {
        return a < b;
    }
};

int main()
{
    set<int,shishishi> A;
    A.insert(1);
    A.insert(4);
    A.insert(2);
    A.insert(3);
    A.insert(5);
    A.insert(5);
    A.insert(3);

    set<int>::iterator it;
    for (it = A.begin(); it != A.end(); it++) {
        cout<<*it<<endl;
    }


    return 0;
}

Map

map/multimap容器的默认构造方式:map<T1,T2> mapA;

T1\T2可以为不同类型,分别代表key和value。

1.插入、遍历函数

#include <iostream>
#include <map>
using namespace std;

int main()
{
    map <int, string> mapA;
//对组插入
    mapA.insert(pair<int, string>(1, "sans"));
    /*  也可以单独声明队组:pair<int, string> p(1, "sans");
        mapA.insert(p);*/

//value_type插入,value_type本质上是map类的内部类
    mapA.insert(map <int, string>::value_type(2, "frisk"));

//[]运算符重载插入,若map中已经有键,则修改对应值
    mapA[3]= "chara";


    map<int, string>::iterator it;
    for (it = mapA.begin(); it != mapA.end(); it++) {
        pair<int, string> P = *it;//利用对组存储迭代器所指的键值对,再分别提取
        int key = P.first;
        string value = P.second;
        cout << key << "  " << value << endl;
    }
/*结果为:1  sans
         2  frisk
         3  chara*/

    return 0;
}

注:使用insert函数插入键值对,若map中已存在相同的键,则不会改变原有的数据,也无法插入新的数据,而使用[ ]插入,若map中已经有键,则修改对应值。


2.获取键对应的值

#include <iostream>
#include <map>
using namespace std;

int main(){

    map<int,string> mapA;

    mapA[1] = "sans";
    mapA[2] = "frisk";
    mapA[3] = "chara";

    cout << mapA[2] << endl;
//结果为frisk,不推荐使用,因为如果写mapA[4]会额外创建新的键值对

    cout << (*mapA.find(3)).second << endl;
//结果为chara
//find()函数返回指向相应pair的迭代器,键值对用Pair存储,可以用.second获取。注意要用括号括起来

    return 0;
}

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值