c++容器各种用法总结

这篇博客总结了C++中的主要容器,包括stack的入栈、出栈、访问栈顶元素等操作,vector的插入、删除、查找和容量调整,set的基本操作如插入、删除、查找,queue的入队、出队以及size检查,以及priority_queue的使用。此外,还介绍了deque的头尾操作和哈希表unordered_map的元素添加、查找等特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章目录

一些共有方法或者特性

find函数

size

注意的是,返回的是一个size_t的数据类型,不是直接的int,所以建立都用一个int去接它,而不是直接使用,比如放在max中,无法与int直接比较的

stack

1、出栈:如 s.pop() 注意并不返回出栈的元素

2、进栈:如 s.push(x)

3、访问栈顶元素:如s.top();

4、判断栈空:如 s.empty() 栈为空时返回true

5、返回栈中元素个数,如:s.size()

vector

find

在vector中没有专门定义的find,所以在vec中查找时要使用统一的find函数

find(v.begin(),v.end(),t)//返回迭代器,减去v.begin()可得到位置

注意与哈希表的内置查找用法区分开

mp.find(t)

assign

一般用来进行部分拷贝或者转移较为好用

v.assign(v1.begin()+1,v1.begin()+3);

插入元素

首先要说明,在遍历的时候是绝对不能插入的,不然会导致迭代器的混乱,只能在静态情况下插入

vector.insert(vector.begin(), 5);

1、push_back(x) 在数组的最后添加元素x。

2、pop_back() 删除最后一个元素,无返回值。

3、at(i) 返回位置i的元素。

4、begin() 返回一个迭代器,指向第一个元素。

5、end() 返回一个迭代器,指向最后一个元素的下一个位置。

6、front() 返回数组头的引用。

7、capacity(x) 为vector分配空间

8、size() 返回数组大小

9、resize(x) 改变数组大小,如果x比之前分配的空间大,则自动填充默认值。

10、insert 插入元素

①a.insert(a.begin(),10); 将10插入到a的起始位置前。
②a.insert(a.begin(),3,10) 将10插入到数组位置的0-2处。

11、erase 删除元素

①a.erase(a.begin()); 将起始位置的元素删除。
②a.erase(a.begin(),begin()+2); 将0~2之间的元素删除。

12、rbegin() 返回一个逆序迭代器,它指向最后一个元素。

13、rend() 返回一个逆序迭代器,它指向的第一个元素前面的位置。

14、clear()清空所有元素。

set

1、begin() 返回一个迭代器,指向第一个元素。

2、end() 返回一个迭代器,指向最后一个元素的下一个位置。

3、clear()清空set的所有元素。

4、empty() 判断是否为空。

5、size() 返回当前元素个数

6、erase(it) 删除迭代器指针it指向的元素。

7、insert(a) 插入元素a

8、count() 查找某个元素出现的次数,只有可能为0或1。

9、find() 查找某个元素出现的位置,如果找到则返回这个元素的迭代器,如果不存在,则返回s.end()

queue

1、入队,如:q.push(x) 将元素x置于队列的末端

2、出队,如: q.pop() 同样不会返回弹出元素的值

3、返回队首元素,如:q.front();

4、返回队尾元素,如:q.back();

5、判断是否为空,如:q.empty();

6、返回队列元素个数,如:q.size();

priority_queue

普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。

在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。
其内部实现是一个堆排序,每次对输入进来的数据按顺序入一个堆中
top 访问队头元素
empty 队列是否为空
size 返回队列内元素个数
push 插入元素到队尾 (并排序)
emplace 原地构造一个元素并插入队列
pop 弹出队头元素
swap 交换内容
一个使用优先队列的例子
定义:priority_queue<Type, Container, Functional>
Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式,当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆
一般是:

//升序队列
priority_queue <int,vector<int>,greater<int> > q;
//降序队列
priority_queue <int,vector<int>,less<int> >q;

//greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)

最后这里是个可以自定义的函数cmp,当使用自定义的时候要把三个参数都写上

#include<iostream>
#include <queue>
using namespace std;
int main() 
{
    //对于基础类型 默认是大顶堆
    priority_queue<int> a; 
    //等同于 priority_queue<int, vector<int>, less<int> > a;
    
    //             这里一定要有空格,不然成了右移运算符↓
    priority_queue<int, vector<int>, greater<int> > c;  //这样就是小顶堆
    priority_queue<string> b;

    for (int i = 0; i < 5; i++) 
    {
        a.push(i);
        c.push(i);
    }
    while (!a.empty()) 
    {
        cout << a.top() << ' ';
        a.pop();
    } 
    cout << endl;

    while (!c.empty()) 
    {
        cout << c.top() << ' ';
        c.pop();
    }
    cout << endl;

    b.push("abc");
    b.push("abcd");
    b.push("cbd");
    while (!b.empty()) 
    {
        cout << b.top() << ' ';
        b.pop();
    } 
    cout << endl;
    return 0;
}

class Solution {
public:
    vector<string> findRelativeRanks(vector<int>& nums) {
        int n = nums.size(), cnt = 1;
        vector<string> res(n, "");
        priority_queue<pair<int, int>> heap; //定义一个pair类型的堆
        for(int i =0; i <n; i++){
            heap.push({nums[i], i}); //放入堆中,自动排序
        }
        for(int i = 0; i < n; i++){
            int dx = heap.top().second;//依次从堆顶取,取出来的就是当前最大的
            heap.pop();
            if(cnt == 1) res[dx] = "Gold Medal";
            else if(cnt == 2) res[dx] = "Silver Medal";
            else if(cnt == 3) res[dx] = "Bronze Medal";
            else res[dx] = to_string(cnt);
            cnt++;
        }
        return res;
    }
};

deque

容器deque和vector非常相似,操作函数基本一致。它采用动态数组来管理元素,提供随机存取,可以在头尾两端进行快速安插和删除元素操作。特别要注意,除了头尾两端,在任何地方安插与删除元素,都将导致指向deque元素的任何pointers references iterators 失效。
使用deque时一般是为了使用头尾增加删除的四个函数,vector只提供了一端的两个函数,少了front端

包括的头文件为:

#include

using namespace std;

声明一个deque时,一般需要前缀std:: ,如std::deque c;

因为类型deque是一个定义在namespace std内的template 。

构造函数:

deque c ; //产生一个空的deque,其中没有任何元素

deque c1(c2); //产生另一个同型deque的副本(所有元素都被拷贝)

deque c(n) ; //产生一个大小为n的deque

deque c(n , elem) ; //产生一个大小为n的deque,

                      //每个元素值都是elem。

dequer c(begin,end); //产生一个deque,以区间[begin ; end]

                      //做为元素初值

析构函数:

c.~ deque() ;销毁所有元素,并释放内存。

非变动性操作

c.size(); //返回当前的元素数量

c.empty(); //判断大小是否为零。等同于c.size() == 0,但可能更快

c.max_size(); //可容纳元素的最大数量

c.at(idx) ; //返回索引为idx所标示的元素。如果idx越界,抛出out_of_range

c[idx] ; //返回索引idx所标示的元素。不进行范围检查

c.front() ; //返回第一个元素,不检查元素是否存在

c.back(); //返回最后一个元素

c.begin(); //返回一个随机迭代器,指向第一个元素

c.end(); //返回一个随机迭代器,指向最后元素的下一位置

变动性操作:

c1 = c2 ; //将c2的所有元素赋值给c1;

c.assign(n , elem); //将n个elem副本赋值给c

c.assing(beg , end); //将区间[beg;end]中的元素赋值给c;

c.push_back(elem); //在尾部添加元素elem

c.pop_back() ; //移除最后一个元素(但不回传)

c.push_front() ; //在头部添加元素elem

c.pop_front() ; //移除头部一个元素(但不回传)

c.erase(pos) ; //移除pos位置上的元素,返回一元素位置

             //如 c.erase( c.begin() + 5)  //移除第五个元素

c.insert(pos , elem); //在pos位置插入一个元素elem,并返回新元素的位置

c.insert(pos , n , elem); //在pos位置插入n个元素elem,无返回值

c.insert(pos , beg , end);

c.resize(num); //将容器大小改为num。可更大或更小。

c.resize(num , elem); //将容器大小改为num,新增元素都为 elem

c.clear(); //移除所有元素,将容器清空

PS:Deque和Vector是智能容器,删除或者增加元素时,其他位置与元素会进行相应的移动。

哈希表unordered_map

STL中的unordered_map使用的是哈希表

支持key的类型

主要是可以用与《操作符的,向pair这样的是不可以的
template <> struct hash;
template <> struct hash;
template <> struct hash;
template <> struct hash;
template <> struct hash<char16_t>;
template <> struct hash<char32_t>;
template <> struct hash<wchar_t>;
template <> struct hash;
template <> struct hash;
template <> struct hash;
template <> struct hash;
template <> struct hash;
template <> struct hash;
template <> struct hash;
template <> struct hash;
template <> struct hash;
template <> struct hash;
template <> struct hash;
template struct hash<T*>;
template <size_t N> struct hash<bitset >;
template <> struct hash;
template <> struct hash;
template <> struct hash;
template <> struct hash;
template struct hash<vector<bool, Allocator> >;

添加元素

map[key] = value;

根据索引key提取value

注意:当key存在的时候会返回这个key对应的value,而不存在的时候则会直接添加进去这个key并且将value设置为1,所以这个只适用于确定key存在的情况下,可以先用find进行判断

使用find查找value

这两个的功能十分相近所以这里放在一起讲
map里面find函数的用法和vector还不太一样,是哈希表名加点加find(key),当元素存在时返回一个迭代器,但这个迭代器通常不好直接利用,当不存在返回的是m.end()所以find通常只用来判断key值是否存在,不用来查找位置,确定存在后可以再使用索引进行提取
注意索引是[] 而函数用()


auto k = map.find(key);//返回迭代器
bool b = map.find(key) == map.end()//判断是否存在

list(双向链表)

stl中的list一般实现是双向链表,这样插入删除更加方便;
但是由于内存不是连续的,使用迭代器时不能对迭代器使用++操作,凡是内存不连续的都不能这样

2.1list中的构造函数:

list() 声明一个空列表;

list(n) 声明一个有n个元素的列表,每个元素都是由其默认构造函数T()构造出来的

list(n,val) 声明一个由n个元素的列表,每个元素都是由其复制构造函数T(val)得来的

list(n,val) 声明一个和上面一样的列表

list(first,last) 声明一个列表,其元素的初始值来源于由区间所指定的序列中的元素

2.2 begin()和end():

通过调用list容器的成员函数begin()得到一个指向容器起始位置的iterator,可以调用list容器的 end() 函数来得到list末端下一位置,相当于:int a[n]中的第n+1个位置a[n],实际上是不存在的,不能访问,经常作为循环结束判断结束条件使用。

2.3 push_back() 和push_front():

使用list的成员函数push_back和push_front插入一个元素到list中。其中push_back()从list的末端插入,而 push_front()实现的从list的头部插入。

2.4 empty():

利用empty() 判断list是否为空。

2.5 resize():

如果调用resize(n)将list的长度改为只容纳n个元素,超出的元素将被删除,如果需要扩展那么调用默认构造函数T()将元素加到list末端。如果调用resize(n,val),则扩展元素要调用构造函数T(val)函数进行元素构造,其余部分相同。

2.6 clear():

清空list中的所有元素。

2.7 front()和back():

通过front()可以获得list容器中的头部元素,通过back()可以获得list容器的最后一个元素。但是有一点要注意,就是list中元素是空的时候,这时候调用front()和back()会发生什么呢?实际上会发生不能正常读取数据的情况,但是这并不报错,那我们编程序时就要注意了,个人觉得在使用之前最好先调用empty()函数判断list是否为空。

2.8 pop_back和pop_front():

通过删除最后一个元素,通过pop_front()删除第一个元素;序列必须不为空,如果当list为空的时候调用pop_back()和pop_front()会使程序崩掉。

2.9 assign():

具体和vector中的操作类似,也是有两种情况,第一种是:l1.assign(n,val)将 l1中元素变为n个T(val)。第二种情况是:l1.assign(l2.begin(),l2.end())将l2中的从l2.begin()到l2.end()之间的数值赋值给l1。

2.10 swap():

交换两个链表(两个重载),一个是l1.swap(l2); 另外一个是swap(l1,l2),都可能完成连个链表的交换。

2.11 reverse():

通过reverse()完成list的逆置。

2.12 merge():

合并两个链表并使之默认升序(也可改),l1.merge(l2,greater()); 调用结束后l2变为空,l1中元素包含原来l1 和 l2中的元素,并且排好序,升序。其实默认是升序,greater()可以省略,另外greater()是可以变的,也可以不按升序排列。

splice方法

就是将list的元素进行拼接,原理就是改变结点指针的指向,效率比较高。

先看看这splice方法的三种声明:
(1)void splice ( iterator position, list<T,Allocator>& x );
功能: 将 list x 中的元素全都移到position处
(2)void splice ( iterator position, list<T,Allocator>& x, iterator it );
功能: 将 list x 中的由迭代器it指向的元素移到position处
(3)void splice ( iterator position, list<T,Allocator>& x, iterator first, iterator last );
功能:将 list x 中的从迭代器 first 到迭代器 last 这一段元素移动到position处

注意:position位置的指定只能是调用者容器中的位置,要剪切的元素是list x中元素
————————————————
版权声明:本文为CSDN博主「beyond559」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41909314/article/details/90575034

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值