文章目录
- 一些共有方法或者特性
- stack
- vector
- find
- assign
- 插入元素
- 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 插入元素
- 11、erase 删除元素
- 12、rbegin() 返回一个逆序迭代器,它指向最后一个元素。
- 13、rend() 返回一个逆序迭代器,它指向的第一个元素前面的位置。
- 14、clear()清空所有元素。
- set
- queue
- priority_queue
- 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(); //返回一个随机迭代器,指向最后元素的下一位置
- 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.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(); //移除所有元素,将容器清空
- 哈希表unordered_map
- list(双向链表)
一些共有方法或者特性
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