C++常用算术及标准库容器算法(Standard Template Library Containers, STLC)

190 阅读12分钟

@TOC

注意,本文内容较为详细,文章简略版可以查阅 C++数据类型及标准库容器(Standard Template Library Containers, STL)

.CPP基本数据类型如有疑问可留言沟通交流Ⅰ. CPP基本数据类型:^{如有疑问可留言沟通交流}

类型关键字
布尔型bool
字符型char
整型int
浮点型float
双浮点型double
无类型void
宽字符型wchar_t

各种变量类型在内存中存储值时需要占用的内存,以及该类型的变量所能存储的最大值和最小值:

类型存储范围
char1 个字节-128 到 127 或者 0 到 255
unsigned char1 个字节0 到 255
signed char1 个字节-128 到 127
int4 个字节-2147483648 到 2147483647
unsigned int4 个字节0 到 4294967295
signed int4 个字节-2147483648 到 2147483647
short int2 个字节-32768 到 32767
unsigned short int2 个字节0 到 65,535
signed short int2 个字节-32768 到 32767
long int8 个字节-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807
signed long int8 个字节-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807
unsigned long int8 个字节0 到 18,446,744,073,709,551,615
float4 个字节精度型占4个字节(32位)内存空间,+/- 3.4e +/- 38 (~7 个数字)
double8 个字节双精度型占8 个字节(64位)内存空间,+/- 1.7e +/- 308 (~15 个数字)
long double16 个字节长双精度型 16 个字节(128位)内存空间,可提供18-19位有效数字。
wchar_t2 或 4 个字节1 个宽字符

注意: 枚举类型(enumeration)是C++中的一种派生数据类型,它是由用户定义的若干枚举常量的集合。 如果一个变量只有几种可能的值,可以定义为枚举(enumeration)类型。所谓"枚举"是指将变量的值一 一列举出来,变量的值只能在列举出来的值的范围内。创建枚举,需要使用关键字 enum
注意: 不同系统会有所差异,一字节为 8 位。
注意: 默认情况下,int、short、long都是带符号的,即 signed。
注意: long int 8 个字节,int 都是 4 个字节,早期的 C 编译器定义了 long int 占用 4 个字节,int 占用 2 个字节,新版的 C/C++ 标准兼容了早期的这一设定。
注意,各种类型的存储大小与系统位数有关,但目前通用的以64位系统为主。以下列出了32位系统与64位系统的存储大小的差别(windows 相同):

系统的存储大小.png

.CPP常用算术如有疑问可留言沟通交流Ⅱ. CPP 常用算术:^{如有疑问可留言沟通交流}

int std::rand();  ->  rand() % n + a
【#include <cstdlib>】https://en.cppreference.com/w/cpp/numeric/random/rand        // 伪随机数
INT_MAX, INT_MIN, LONG_MAX, LONG_MIN
【#include <climits>】https://en.cppreference.com/w/cpp/header/climits             // 限值
INFINITY
【#include <cmath>】https://en.cppreference.com/w/cpp/numeric/math/INFINITY        // 无穷大
float       ceil ( float num );
double      ceil ( double num );
long double ceil ( long double num );
auto value = std::ceil(+2.4); // 3.000000
auto value = std::ceil(-2.4); // -2.000000
auto value = std::ceil(-0.0); // -0.000000#include <cmath>】https://en.cppreference.com/w/cpp/numeric/math/ceil            // 向上取整
float       floor ( float num );
double      floor ( double num );
long double floor ( long double num );
auto value = std::floor(+2.7); // 2.000000
auto value = std::floor(-2.7); // -3.000000
auto value = std::floor(-0.0); // -0.000000#include <cmath>】https://en.cppreference.com/w/cpp/numeric/math/floor           // 向下取整
float       round ( float num );
double      round ( double num );
long double round ( long double num );
auto value = std::round(2.3); // 2
auto value = std::round(2.5); // 3
auto value = std::round(2.7); // 3
auto value = std::round(-2.3); // -2
auto value = std::round(-2.5); // -3
auto value = std::round(-2.7); // -3
auto value = std::round(-0.0); // -0#include <cmath>】https://en.cppreference.com/w/cpp/numeric/math/round           // 四舍五入
int         std::abs( int num );
long        std::abs( long num );
long long   std::abs( long long num );
float       std::abs( float num );
double      std::abs( double num );
long double std::abs( long double num );
【#include <cmath>】https://en.cppreference.com/w/cpp/numeric/math/abs             // 绝对值
auto max_value = std::max(69, 96);
auto max_value = std::max('q', 'p');
auto max_value = std::max({010, 10, 0X10, 0B10});
auto max_value = std::max({ "string long long", "string short", "string middle" },
[](const std::string_view s1, const std::string_view s2)
                   {
                       return s1.size() < s2.size(); // 重载operator<
                   });
【#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/max            // 最大值
auto min_value = std::min(1, 9999)
auto min_value = std::min('a', 'b')
auto min_value = std::min({"foo", "bar", "hello"},
[](const std::string_view s1, const std::string_view s2)
                   {
                       return s1.size() < s2.size(); // 重载operator<
                   });
【#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/min            // 最小值
int value = std::gcd(2*2*3, 2*3*3); // 2*3     (greatest common divisor)#include <numeric>】https://en.cppreference.com/w/cpp/numeric/gcd                // 最大公约数
int value = std::lcm(2*2*3, 2*3*3); // 2*2*3*3 (least common multiple)#include <numeric>】https://en.cppreference.com/w/cpp/numeric/gcd                // 最小公倍数
float       sqrt ( float num );
double      sqrt ( double num );
long double sqrt ( long double num );
auto value = std::sqrt(100); // 结果为 100#include <cmath>】https://en.cppreference.com/w/cpp/numeric/math/sqrt             // 平方根
float       pow ( float base, float exp );
double      pow ( double base, double exp );
long double pow ( long double base, long double exp );
auto value = std::pow(100, 0.5); // 结果为 10
auto value = std::pow(2, 10); // 结果为 1024#include <cmath>】https://en.cppreference.com/w/cpp/numeric/math/pow             // 次幂
float       log ( float num );
double      log ( double num );
long double log ( long double num );
auto value = std::log(1024)/std::log(2); // 结果为 10#include <cmath>】https://en.cppreference.com/w/cpp/numeric/math/log             // 对数
float       sin ( float num );
double      sin ( double num );
long double sin ( long double num );
float       cos ( float num );
double      cos ( double num );
long double cos ( long double num );
float       tan ( float num );
double      tan ( double num );
long double tan ( long double num );
float       asin ( float num );
double      asin ( double num );
long double asin ( long double num );
float       acos ( float num );
double      acos ( double num );
long double acos ( long double num );
float       atan ( float num );
double      atan ( double num );
long double atan ( long double num );
// 注 三角函数中 num 均以弧度计量#include <cmath>】https://en.cppreference.com/w/cpp/numeric/math/sin           // 正弦#include <cmath>】https://en.cppreference.com/w/cpp/numeric/math/cos           // 余弦#include <cmath>】https://en.cppreference.com/w/cpp/numeric/math/tan           // 正切#include <cmath>】https://en.cppreference.com/w/cpp/numeric/math/asin          // 反双曲正弦#include <cmath>】https://en.cppreference.com/w/cpp/numeric/math/acos          // 反双曲余弦#include <cmath>】https://en.cppreference.com/w/cpp/numeric/math/atan          // 反双曲正切
std::complex<double> z1 = 1i * 1i; // 计算结果为 (-1.0,0.0) 虚数单位平方#inclu <complex>】https://en.cppreference.com/w/cpp/numeric/complex            // 虚数

.CPPSTL常用容器如有疑问可留言沟通交流Ⅲ. CPP STL 常用容器:^{如有疑问可留言沟通交流}

Ⅲ.1 容器 本器

容器库 是类模板与算法的汇集,允许程序员简单地访问常见数据结构,例如队列、链表和栈。有两 (C++11 前)三 (C++11 起)类容器:

  • 顺序容器
  • 关联容器
  • 无序关联容器
  • 容器适配器

各容器具体信息如下:

STL ContainerHeaderApplications
array< array >顺序容器,封装固定大小数组的容器。
vector< vector >顺序容器,直接访问任意元素,快速插入、删除尾部元素。采用连续的线性空间,可以将其理解为一个“变长数组”。
deque< deque >顺序容器,直接访问任意元素,快速插入、删除头部和尾部元素,基于数组实现。
list< list >顺序性容器,快速插入、删除任意位置元素,以双向链表的形式实现。
set< set >关联容器,快速查询元素,无重复关键字。基于红黑树实现。
multiset< set >关联容器,与set相同,但允许重复关键字。基于红黑树实现。
unordered_set<unordered_set>
unordered_multiset<unordered_set>
map< map >关联式容器,Key/value pair mapping(键值对映射)。不允许重复关键字,使用关键字快速查询元素。基于红黑树实现。
multimap< map >关联容器,与map相同,但允许重复关键字。基于红黑树实现。
unordered_map<unordered_map>
unordered_multimap<unordered_map>
stack< stack >容器适配器,后进先出容器,基于deque实现。
queue< queue >容器适配器,先进先出容器,基于deque实现。
priority_queue< queue >容器适配器,高优先级元素先删除。基于vector实现,默认实现的就是大根堆。

参考
C++ STL 容器 - (oi-wiki.org)
C++ STL 容器 - (biancheng.net)

Ⅲ.2 自定义排序

C++ 可以结合函数、函数指针、函数对象、lambda表达式 等谓词(predicate) 实现容器的自定义排序。

1.堆的自定义排序
struct cmp{
	bool operator() (const T &a, const  T &b) const{
		return a < b; //大根堆, 小根堆用> 唯一一个反着的
	}
};
priority_queue<T, vector<T>, cmp> p;
priority_queue<T, vector<T>, std::less<int>> p;
priority_queue<T, vector<T>, std::greater<int>> p;
【#include <queue>】https://en.cppreference.com/w/cpp/container/priority_queue  // 优先队列

2.set的自定义排序
struct cmp{
	bool operator() (const T &a, const  T &b) const{
		return a < b; 
	}
};
set<T, cmp> s;
std::set<int, std::less<int>()> ss; // 升序(默认)
std::set<int, std::greater<int>()> ss; // 降序#include <set>】https://en.cppreference.com/w/cpp/container/set               // 集合
有序关联容器 - 红黑树

3.map的自定义排序,如果是单元素, 直接用反向迭代器,auto   rbegin, rend, ++
如果是pair, 就存到vector中自定义排序。
也可以参考堆的那种:
struct cmp{
	bool operator() (const T1 &a, const T1 &b) const{ //一般都是T
		return a < b; 
	}
};
map<T1, T2, cmp> m;
std::map<int, T2, std::less<int>()> mm; // 升序(默认)
std::map<int, T2, std::greater<int>()> mm; // 降序#include <map>】https://en.cppreference.com/w/cpp/container/map               // 映射
有序关联容器 - 红黑树

4.排序也要注意是否需要动态更新排序。
补充:STL中priority_queuesetmap、sort的自定义比较函数。STL中,
priority_queue默认是less,也就说大顶堆;
set默认是less,也就是说用迭代器迭代的时候是从小到大排序的。
map默认是less,也就说用迭代器迭代的时候默认是小的排在前面;
std::sort算法的默认排序为less,也就是说从小到大排序;

Ⅲ.3 运算符重载

C++ 中的自定义数据类型可以通过重载 operator< 结合 set、map 实现自动排序。

// 自定义数据类型
struct Node{
    // 方法
    Node():val(0), row(0), col(0) {}
    Node(int v, int r, int c):val(v), row(r), col(c) {}
    // 运算符重载
    bool operator<(const Node & node) const {
        if( (this->col < node.col) || (this->col == node.col && this->row < node.row) ||
        (this->col == node.col && this->row == node.row && this->val < node.val) ){return true;}
        return false;
    }
    // 属性
    int val;
    int row;
    int col;
};
// struct 常用于存储轻量级的数据对象;class 常用于存储或表示复杂的功能

.CPPSTLC常用算法如有疑问可留言沟通交流Ⅳ. CPP STLC 常用算法:^{如有疑问可留言沟通交流}

标准模板库 (Standard Template Library, STL) 提供了大约 100 个实现算法的模版函数,基本都包含在 <algorithm> 之中,还有一部分包含在 <numeric><functional>C++常用算法参考

std::vector<int> v {3, 1, -4, 1, 5, 9};
// 查找容器中的最值
std::vector<int>::iterator std::min_element(v.begin(), v.end()); 
std::vector<int>::iterator std::min_element(v.begin(), v.end(), [](int a, int b){ return std::abs(a) < std::abs(b); }); // 自定义比较 重载 operator< (绝对值比较)#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/min_element       // 最小值
std::vector<int>::iterator std::max_element(v.begin(), v.end());
std::vector<int>::iterator std::max_element(v.begin(), v.end(), [](int a, int b){ return std::abs(a) < std::abs(b); }); // 自定义比较 重载 operator< (绝对值比较)#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/max_element       // 最大值

// 二分查找(默认容器升序,即容器中元素由小到大排好序了)
bool std::binary_search(v.begin(), v.end(), int value);
// 在一个升序容器中进行二分查找,检查容器中是否存在等价于 value 的元素。如果不存在则返回 false#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/binary_search     // 确定元素是否存在于升序容器的[begin, end)区间中
std::vector<int>::iterator std::lower_bound(v.begin(), v.end(), int value); // 默认容器升序
// 在一个升序容器的[begin, end)区间中进行二分查找,返回指向第一个 大于等于 x 的元素的位置的迭代器。如果不存在这样的元素,则返回尾迭代器end()。
std::vector<int>::iterator std::lower_bound(v.begin(), v.end(), int value, std::greater<int>());
// 在一个降序容器的[begin, end)区间中进行二分查找,返回指向第一个 小于等于 x 的元素的位置的迭代器。如果不存在这样的元素,则返回尾迭代器end()。#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/lower_bound       // 返回指向第一个大于等于给定值的元素的迭代器
std::vector<int>::iterator std::upper_bound(v.begin(), v.end(), int value);
// 在一个升序容器的[begin, end)区间中进行二分查找,返回指向第一个 大于 x 的元素的位置的迭代器。如果不存在这样的元素,则返回尾迭代器end()。
std::vector<int>::iterator std::upper_bound(v.begin(), v.end(), int value, std::greater<int>());
// 在一个降序容器的[begin, end)区间中进行二分查找,返回指向第一个 小于 x 的元素的位置的迭代器。如果不存在这样的元素,则返回尾迭代器end()。#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/upper_bound       // 返回指向第一个大于给定值的元素的迭代器

// 对容器中的元素计数
int count = std::count(v.cbegin(), v.cend(), int target);  // 计算容器内中 target 出现的个数
// 由 lambda 表达式计算能被 4 整除的元素个数
int count = std::count_if(v.begin(), v.end(), [](int i) { return i % 4 == 0; }); // 条件计数#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/count               // 元素计数

std::vector<int>::iterator std::find(v.begin(), v.end(), int value); // 未找到时返回 v.end()#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/find                // 顺序查找
auto a = 3;
std::vector<int>::iterator std::find_if(v.begin(), v.end(), [&](const int &b){ 
            return ((a*b-a)<=0);
            }); // 可以结合未找到时返回 v.end()#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/find_if             // 条件查找
std::vector<int>::iterator std::binary_search(v.begin(), v.end(), int value); // 要求容器已排序,未找到时返回 v.end()#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/binary_search       // 二分查找
std::vector<int>::iterator std::adjacent_find(v.begin(), v.end());
// 查找首对相邻的相同元素,未找到时返回 v.end()#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/adjacent_find       // 查找邻同
std::vector<int>::iterator std::adjacent_difference(v.begin(), v.end(), v.begin());
// 计算相邻元素之间的差#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/adjacent_difference // 计算邻差

long long int sum = std::accumulate(v.begin(), v.end(), 0LL); // 累加
// unsigned long long int sum = std::accumulate(v.begin(), v.end(), 0ULL);
// 0LL(0ULL) 用于防止 std::accumulte 计算结果溢出
int std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>()); // 累积#include <numeric>】https://en.cppreference.com/w/cpp/algorithm/accumulate
std::reduce(...); // 用法同 std::accumulate,但不依序执行#include <numeric>】https://en.cppreference.com/w/cpp/algorithm/reduce
std::vector<int>::iterator std::partial_sum(x.begin(), x.end(), y.begin());
// 设源容器为 x,目标容器 y 中的元素为 y[i]=x[0]+x[1]+...+x[i]#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/partial_sum       // 前缀和

std::for_each(v.begin(), v.end(), [](int &n){ n++; });
【#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/for_each          // 遍历
std::transform(svalue.begin(),svalue.end(), svalue.begin(), ::tolower);   // 字母转小写
std::transform(svalue.begin(),svalue.end(), svalue.begin(), ::toupper);   // 字母转大写#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/transform         // 变换

void std::sort(v.begin(), v.end()); // 默认 operator<
void std::sort(v.begin(), v.end(), std::less<int>());
void std::sort(v.begin(), v.end(), std::greater<int>());
void std::sort(v.begin(), v.end(), [](int a, int b){ return std::abs(a) < std::abs(b); });
bool std::is_sorted(Nums.begin(), Nums.end(), std::less<int>()); // 判断容器是否升序
bool std::is_sorted(Nums.begin(), Nums.end(), std::greater<int>()); // 判断容器是否降序#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/sort              // 排序
void std::stable_sort(...); // 用法同 std::sort(),稳定排序,同时保持相等的元素之间的顺序#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/stable_sort       // 排序
void std::nth_element(v.begin(), v.begin() + 3, v.end()); // 默认 operator<
void std::nth_element(v.begin(), v.begin() + 3, v.end(), [](int a, int b){ return std::abs(a) < std::abs(b); });
// 按指定范围进行元素划分,即 找出序列中第 n 大的元素,使其左边均为小于它的数,右边均为大于它的数#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/nth_element       // 划分
// 在 std::sort 后利用 std::unique 可以去除所有重复元素:
    std::sort(v.begin(), v.end()); // 容器排序
    auto last = std::unique(v.begin(), v.end()); // 返回值为指向 去重后 元素集合结尾的迭代器,原容器大小不变
    v.erase(last, v.end()); // 去除尾部(由last到end)重复元素#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/unique            // 去重

void std::reverse(v.begin(), v.end());
【#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/reverse           // 翻转
std::vector<int>::iterator std::rotate(v.begin(), v.begin() + 3, v.end());
【#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/rotate            // 旋转

void std::shuffle(v.begin(), v.end(), std::mt19937 {std::random_device{}()}); // 随机打乱数组#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/random_shuffle    // 随机打乱
std::vector<int>::iterator std::sample(v1.begin(), v1.end(), v2.begin(), 4, std::mt19937 {std::random_device{}()}); // 从 v1 中随机选取4个元素放入 v2 中#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/sample            // 随机抽样

bool std::is_permutation(v1.begin(), v1.end(), v2.begin()); // 判断一个序列是否为另一个序列的排列#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/is_permutation    // 排列
bool std::next_permutation(v.begin(), v.end());
// 将当前排列更改为 全排列 中的下一个排列。
// 如果当前排列已经是 全排列中的最后一个排列(元素完全从大到小排列),函数返回 false 
// 并将排列更改为 全排列 中的第一个排列(元素完全从小到大排列);
// 否则,函数返回 true。#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/next_permutation  // 排列
bool std::prev_permutation(...); // 用法同 std::next_permutation(),将当前排列更改为 全排列中的上一个排列#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/prev_permutation  // 排列

end.友情链如有疑问可留言沟通交流end. 友情链接^{如有疑问可留言沟通交流}

  1. C++常用算术
  2. C++进制转换及 std::string、std::stringstream、std::bitset 常用方法
  3. C++数据类型及标准库容器(Standard Template Library Containers, STL)
  4. ...

代码调试不易,转载请标明出处!
如果感觉本文对您有帮助,请留下您的赞,您的支持是我坚持写作分享的最大动力,谢谢!

References
0.Standard C++
1.cppreference.com
2.apiref.com/cpp
3.cplusplus.com
4.C++ 标准库参考 | Microsoft Learn
5.C++ 教程 | 菜鸟教程
6.C++ 二进制、字符串、十六进制、十进制
7.C++中substr()函数用法
可以肯定的是学海无涯,这篇文章也会随着对 C++ 的深入学习而持续更新,
欢迎各位在评论区留言进行探讨交流。