算法笔记之STL用法总结

本文章是对《算法笔记》中STL库用法的一个精炼总结,这确实是一本好书,对STL的讲解由浅入深,我对经常用到的方法做了一个摘要。

STL用法

vector

主要用来作为数组使用,可以在一些元素个数不确定的场合存储数据。也用于实现邻接表来存储图。

使用时需要包含头文件

#include <vector>

定义一个vector

vector<int> name;
vector<vector<int> > name;
vector<int> array[Size]; // 定义一个vector数组

访问元素

可通过下标进行访问,也可以使用迭代器进行访问

// 使用下标方式就和用一维数组一样,习惯这样用了

// 迭代器可以理解为一种类似于指针的东西,用法如下

for(vector<int>::iterator it = vi.begin(); it != vi.end(); it++){
    printf("%d ", *it);
}

常用API

  • 添加元素

    • push_back(Elem)
  • 删除尾元素

    • pop_back()
  • 获取vector中元素的个数

    • size()
  • 清空所有元素

    • clear()
  • 插入元素

    • 向vector的任意迭代器处插入元素

    • vi.insert(position, value)

    • vi.insert(vi.begin() + 2, -100);
      
  • 清除元素

    • 使用.erase(),有两种用法,既可以删除单个元素,也可以删除一个区间内的所有元素

    • // 删除迭代器为it处的元素
      vi.erase(vi.begin() + 3);
      
    • // 删除一个区间的所有元素
      vi.erase(vi.begin() + 1, vi.end())
      

set

是数学中的集合,是一个内部自动有序而且不含重复元素的容器。

使用时需要包含头文件

#include <set>

定义一个set

set<int> name;

访问时只能通过迭代器访问

for(set<int>::iterator it = st.begin(); it != st.end(); it++){
    printf("%d", *it);
}

常用API

  • 插入
    • insert(val)
    • 时间复杂度O(logN), 自动递增排序并去重
  • 查找
    • find(val)
    • 返回该元素的迭代器,找不到就返回最后一个元素的迭代器
  • 清除
    • erase,可以删除单个元素,也可以删除一个区间里的元素
    • 删除单个元素由两种用法
      • 既可以传入迭代器
      • 又可以传入所要删除的值
    • 删除一个区间内的元素,左闭右开
  • 获取大小
    • size
  • 清空元素
    • clear

string

使用时需要包含头文件

#include <string>

定义一个string 变量

string str = "abcd";

string中的内容可以通过下标去访问,也可以使用迭代器,和vector差不多。输入输出整个字符串只能用cin和cout

cin>>str;
cout<<str;

其实也可以用.c_str()方法将string转化为字符数组然后printf

常用API

  • operator +=

    • 可以将两个string直接拼接起来
  • compare operator

    • == != < <= > >=
    • 比较规则时字典序
  • 长度

    • length()
    • size()
  • insert()

    • insert(position, string)
      • 在pos处插入一个子串
    • insert(it, it2, it3)
      • it为原字符串的欲插入位置, it2和it3是待插入字符串的首尾迭代器,左开右闭
  • erase()

    • 和vector相似,没怎么用过这个功能

    • 删除一个区间时可以指定起始位置+字符个数

      • str.erase(pos, length)
  • 清空数据

    • clear()
  • 获取子串

    • str.sub(pos, len)
      • 返回从pos号位开始,长度为len的子串
  • 查找

    • find(str2)
    • 如果str2是str的子串时,返回其在str中第一次出现的位置,否则返回string::npos
      • 可以认为这个值为-1
  • replace

    • str.replace(pos, len, str2)
      • 把str从pos号位开始,长度为len的子串替换为str2
    • str.replace(str.begin(), str.begin()+5, str2)
      • 也可以通过迭代器来确定要替换的范围

map

重点其实在于哈希方法(比如字符串哈希),C++ 还有unordered_map,只映射不按key排序,速度比较快,需要单独导入。

定义

map<typename, typename> m;
map<string, int> m;

访问容器内的元素可以直接使用下标,也可以使用迭代器。

使用下表时如果没有就会返回0

使用迭代器时,元素的key是first, 值是second. 使用it->first, it->second访问

map<char, int> m;
m['c'] = 20;

for(map<char, int>::iterator it = m.begin(); it != mp.end(); it++){
    printf("%c, %d\n", it->first, it->second);
}

常用API

  • find(key)
    • 返回键为key的映射的迭代器
  • erase()
    • 传入要删除单个元素的迭代器,迭代器区间
  • size()
    • 获取尺寸
  • clear
    • 清空
  • insert
    • 插入键值对,键值对可用pair

queue

这就是喜闻乐见的队列,先进先出,

主要是在BFS的时用到了。

#include <queue>
using namespace std;

int main(void){
    queue<int> q;
    
    q.push(1);
    q.front(); // 队首
    q.back();  // 队尾
    
    return 0;
}

常用API

  • push()
    • 入队
  • front()
    • 获取队首元素
  • back()
    • 获取队尾元素
  • pop()
    • 令队首元素出队,只是出队,不会返回值
  • empty()
    • 判断是否为空
  • size()
    • 返回queue内元素的个数

优先队列priority_queue

优先队列,底层用堆来实现,队首元素一定是当前队列中优先级最高的那一个。每次push元素的时候都会自动动态调整。

优先级是怎么规定的呢?

对于基本数据类型(int, double, char),优先级一般是数字大的优先级越高,下列两个是等价的

priority_queue<int> q;
priority_queue<int, vector<int>, less<int> > q;
priority_queue<char, vector<char>, less<int> > q;

对于第三个参数, less 表示数字大的优先级越大, greater表示数字小的优先级越大。

那么结构体该怎么办呢?

需要重载运算符,用法如下。

struct fruit{
    string name;
    int price;
    friend bool operator < (fruit f1, fruit f2){
        return f1.price < f2.price;
    }
};

priority_queue<fruit> q;

在这个例子中是按照水果的价格越高,优先级越高。如果想让价格低的水果为高优先级,只需要把return中的 < 改成 >。记住,和sort中的cmp函数相反!

当然也可以把重载运算符写在外面。

#include <queue>

struct fruit {
    string name;
    int price;
}f1, f2, f3;

struct cmp{
    bool operator () (fruit f1, fruit f2){
        return f1.price > f2.price; // 价格低,优先级高
    }
}

priority_queue<fruit, vector<fruit>, cmp> q;

常用API

  • 入队 push
  • 取队首元素
    • top()
    • 只有top这一种方法
  • 队首元素出队
    • pop()
  • 判断是否为空
    • empty()
  • 获取元素个数
    • size()

stack

这是喜闻乐见的栈 🙂

stack<int> st;

st.push(1);
int a = st.top();
st.pop();

常用API

  • 入栈
    • push()
  • 获取栈顶元素
    • top()
  • 弹出栈顶元素
    • pop()
  • 判断是否为空
    • empty()
  • 获取元素个数
    • size()

pair

使用pair需要先导入头文件 导入也行。可以把它看作只包含两个元素的结构体,访问第一个元素用.first, 访问第二个元素用.second。

pair的用途主要在于

  • 代替二元结构体
  • 作为map的键值对进行插入
pair<int, int> p1;

p1.first = 1;
p1.second = 2;

pair<int, int> p2("has", 3);

map<string, int> mp;

mp.insert(make_pair("halo", 1));
mp.insert(pair<string, int>("ha", 10));

p1 < p2;
p1 == p2;

常用函数

  • 比较操作数
    • ==, !=, <, <=, >, >=
    • 以first的大小为标准,first相等时才去判别second

algorithm头文件下的常用函数

max(), min()

max(x, y) 返回最大

min(x, y) 返回最小

abs()

​ 求绝对值

swap()

swap(a, b),用于交换a和b的值

reverse()

reverse(it, it2)可以将数组指针在[it, it2)之间的元素或容器的迭代器在这个范围内反转

next_permutation()

给出一个序列在全排列中的下一个序列,达到全排列的最后一个时会返回false

int a[10] = {1, 2, 3};
do{
	printf("%d %d %d\n", a[0], a[1], a[2]);
}while (next_permutation(a, a+3));

fill()

用于将数组或者容器中的某一段区间赋为某个相同的值,它和memset不同,可以赋任意值。

memset咋用来着?void *memset(void *str, int c, size_t n)

fill的用法如下

int a[10] = {1, 2, 3};
fill(a, a+N, Value);

sort

到排序啦!

sort(首元素地址,尾元素地址的下一个地址,比较函数(默认递增))

int a[6] = {9, 4, 2, 5, 6, -1};
sort(a, a+4); // 对前3个元素进行排序

我们当然也可以自己手动实现比较函数cmp

比如按照递增顺序可以这么写

bool cmp(int a, int b){
    return a > b;
}

递减咋写,把a>b 换成a<b就行啦。

当然,我们也可以对结构体数组进行排序,这是非常灵活的

bool cmp(node a, node b){
    if(a.x != b.x)
        return a.x > b.x;
    return a.y > b.y;
}

sort也能用于对容器的排序之中,只有vector, string, deque可以用,使用红黑树实现的容器(set, map)本身就是有序的,也就不用排序了。

sort(vi.begin(), vi.end(), cmp);

bool cmp1(string a, string b){
    return a.length() < b.length();
}

string str[3] = {"1111", "111", "11"};
sort(str, str+3, cmp1);

lower_bound()和upper_bound()

需要用在一个有序数组或容器之中, lower_bound(first, last, val)用于寻找在数组或者容器[first, last)范围内第一个值大于等于val的元素的位置或者迭代器, upper_bound()返回在[first, last)范围内第一个值大于val的元素的位置。若没有需要寻找的元素,则返回可以插入该元素的位置的指针或迭代器。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值