C++性能优化十大技巧

linbojue
• 阅读 0

1、非修改序列算法 这些算法不会改变它们所操作的容器中的元素。

1.1 find 和 find_if find(begin, end, value):查找第一个等于 value 的元素,返回迭代器(未找到返回 end)。 find_if(begin, end, predicate):查找第一个满足谓词的元素。 find_end(begin, end, sub_begin, sub_end):查找子序列最后一次出现的位置。 vector nums = {1, 3, 5, 7, 9};

// 查找值为5的元素 auto it = find(nums.begin(), nums.end(), 5); if (it != nums.end()) { cout << "found: " << *it << endl; // 输出:5 }

// 查找第一个大于6的元素 auto it2 = find_if(nums.begin(), nums.end(), [](int x) { return x > 6; }); cout << "first >6: " << *it2 << endl; // 输出:7

// 查找子序列 vector sub = {3, 5}; auto it3 = find_end(nums.begin(), nums.end(), sub.begin(), sub.end()); if (it3 != nums.end()) { cout << "subsequence starts at index: " << it3 - nums.begin() << endl; // 输出:1 } AI写代码

1.2 count 和 count_if count(begin, end, value):统计等于 value 的元素个数。 count_if(begin, end, predicate):统计满足谓词(predicate)的元素个数。 std::vector vec = {1, 2, 3, 2, 4, 2}; int cnt = std::count(vec.begin(), vec.end(), 2); // 计数2的个数,结果为3 int even_cnt = std::count_if(vec.begin(), vec.end(), [](int x) { return x % 2 == 0; }); // 偶数个数,结果为4 AI写代码 1.3 for_each 对范围内的每个元素应用一个函数

std::vector vec = {1, 2, 3, 4, 5}; std::for_each(vec.begin(), vec.end(), [](int& x) { x *= 2; // 将每个元素乘以2 }); // 现在vec变为{2, 4, 6, 8, 10} AI写代码 1.4 equal 与 mismatch equal(b1, e1, b2):判断两个范围 [b1,e1) 和 [b2, b2+(e1-b1)) 是否相等。 mismatch(b1, e1, b2):返回两个范围中第一个不相等元素的迭代器对(pair)。 vector a = {1, 2, 3}; vector b = {1, 2, 4}; vector c = {1, 2, 3, 4};

// 比较a和b的前3个元素 bool is_equal = equal(a.begin(), a.end(), b.begin()); cout << "a == b? " << boolalpha << is_equal << endl; // 输出:false

// 查找a和c的第一个不匹配元素 auto mis = mismatch(a.begin(), a.end(), c.begin()); if (mis.first != a.end()) { cout << "mismatch: " << *mis.first << " vs " << *mis.second << endl; // 无输出(a和c前3元素相等) } AI写代码

1.5 all_of, any_of, none_of 检查范围内元素是否全部、存在或没有满足条件的

std::vector vec = {2, 4, 6, 8}; bool all_even = std::all_of(vec.begin(), vec.end(), [](int x) { return x % 2 == 0; }); // true bool any_odd = std::any_of(vec.begin(), vec.end(), [](int x) { return x % 2 != 0; }); // false bool none_negative = std::none_of(vec.begin(), vec.end(), [](int x) { return x < 0; }); // true AI写代码

2、修改序列算法 这些算法会修改它们所操作的容器中的元素。

2.1 copy 和 copy_if copy(begin, end, dest):将 [begin, end) 中的元素复制到 dest 开始的位置。 copy_if(begin, end, dest, predicate):复制满足谓词的元素到 dest。 vector src = {1, 2, 3, 4, 5}; vector dest(5); // 需预先分配足够空间

// 复制所有元素 copy(src.begin(), src.end(), dest.begin()); // dest: [1,2,3,4,5]

// 复制偶数元素到新容器 vector evens; copy_if(src.begin(), src.end(), back_inserter(evens), [](int x) { return x % 2 == 0; }); // evens: [2,4] AI写代码

注意:back_inserter(dest) 会自动调用 push_back,无需提前分配空间。

2.2 transform 对范围内的每个元素应用一个函数,并将结果存储在另一个范围内

vector nums = {1, 2, 3}; vector squares(3);

// 计算平方(单参数转换) transform(nums.begin(), nums.end(), squares.begin(), [](int x) { return x * x; }); // squares: [1,4,9]

// 两容器元素相加(双参数转换) vector a = {1, 2, 3}; vector b = {4, 5, 6}; vector sum(3); transform(a.begin(), a.end(), b.begin(), sum.begin(), [](int x, int y) { return x + y; }); // sum: [5,7,9] AI写代码

2.3 replace、replace_if与 replace_copy replace(begin, end, old_val, new_val):将所有 old_val 替换为 new_val。 replace_if(begin, end, predicate, new_val):替换满足谓词的元素。 replace_copy(begin, end, dest, old_val, new_val):复制时替换元素(不修改原容器)。 vector nums = {1, 2, 3, 2, 5};

// 替换所有2为20 replace(nums.begin(), nums.end(), 2, 20); // nums: [1,20,3,20,5]

// 替换大于10的元素为0 replace_if(nums.begin(), nums.end(), [](int x) { return x > 10; }, 0); // nums: [1,0,3,0,5]

// 复制时替换3为300(原容器不变) vector res; replace_copy(nums.begin(), nums.end(), back_inserter(res), 3, 300); // res: [1,0,300,0,5] AI写代码

2.4 remove、remove_if 与 erase remove(begin, end, value):将等于 value 的元素 “移动” 到容器末尾,返回新的逻辑尾迭代器(不实际删除元素,需配合 erase)。 remove_if(begin, end, predicate):移动满足谓词的元素到末尾。 vector nums = {1, 2, 3, 2, 4};

// 逻辑删除所有2(移动到末尾) auto new_end = remove(nums.begin(), nums.end(), 2); // nums: [1,3,4,2,2]

// 物理删除(真正移除元素) nums.erase(new_end, nums.end()); // nums: [1,3,4]

// 结合lambda删除偶数 nums = {1, 2, 3, 4, 5}; nums.erase(remove_if(nums.begin(), nums.end(), [](int x) { return x % 2 == 0; }), nums.end()); // nums: [1,3,5] AI写代码

2.5 unique 移除范围内连续的重复元素,返回新的逻辑结尾迭代器。通常与erase结合使用。

std::vector vec = {1, 1, 2, 2, 3, 3, 3, 4, 5}; auto last = std::unique(vec.begin(), vec.end()); vec.erase(last, vec.end()); // vec变为{1, 2, 3, 4, 5} AI写代码 2.6 reverse 反转范围内的元素顺序

std::vector vec = {1, 2, 3, 4, 5}; std::reverse(vec.begin(), vec.end()); // vec变为{5, 4, 3, 2, 1} AI写代码 2.7 rotate 旋转范围内的元素,使中间元素成为新的第一个元素

std::vector vec = {1, 2, 3, 4, 5}; std::rotate(vec.begin(), vec.begin() + 2, vec.end()); // 以3为起点旋转,vec变为{3, 4, 5, 1, 2} AI写代码 2.8 shuffle 随机重排范围内的元素(需要C++11或更高版本)

#include #include

std::vector vec = {1, 2, 3, 4, 5}; std::random_device rd; std::mt19937 g(rd()); std::shuffle(vec.begin(), vec.end(), g); // 随机打乱vec中的元素 AI写代码 3、排序和相关算法 3.1 sort、stable_sort 与 partial_sort sort(begin, end):对元素进行快速排序(不稳定,平均时间复杂度 O (n log n))。 stable_sort(begin, end):稳定排序(相等元素相对位置不变)。 partial_sort(begin, mid, end):部分排序,使 [begin, mid) 为整个范围中最小的元素并排序。 std::vector vec = {5, 3, 1, 4, 2}; std::sort(vec.begin(), vec.end()); // 默认升序,vec变为{1, 2, 3, 4, 5} std::sort(vec.begin(), vec.end(), std::greater()); // 降序,vec变为{5, 4, 3, 2, 1} std::sort(vec.begin(), vec.end(), [](int a, int b) { return a < b; }); // 升序,自定义比较

std::vector<std::pair<int, int>> vec = {{1, 2}, {2, 1}, {1, 1}, {2, 2}}; std::stable_sort(vec.begin(), vec.end(), [](const auto& a, const auto& b) { return a.first < b.first; // 按first排序,保持相等元素的相对顺序 });

std::vector vec = {5, 3, 1, 4, 2, 6}; // 将最小的3个元素放在前面并排序 std::partial_sort(vec.begin(), vec.begin() + 3, vec.end()); // 现在vec前三个元素是1, 2, 3,后面是未排序的4, 5, 6 AI写代码

3.2 nth_element 重新排列范围,使得指定位置的元素等于排序后的元素,并且左边的元素都不大于它,右边的元素都不小于它

std::vector vec = {5, 3, 1, 4, 2, 6}; // 找到第三小的元素(索引2) std::nth_element(vec.begin(), vec.begin() + 2, vec.end()); // 现在vec[2]是3,它左边的元素<=3,右边的>=3 AI写代码 3.3 binary_search、lower_bound、upper_bound 需在已排序的容器上使用

binary_search(begin, end, value):判断 value 是否存在(返回 bool)。 lower_bound(begin, end, value):返回第一个不小于 value 的元素迭代器。 upper_bound(begin, end, value):返回第一个大于 value 的元素迭代器。 vector sorted = {1, 3, 3, 5, 7}; // 必须先排序

// 判断3是否存在 bool exists = binary_search(sorted.begin(), sorted.end(), 3); // true

// 查找第一个>=3的元素 auto lb = lower_bound(sorted.begin(), sorted.end(), 3); cout << "lower_bound index: " << lb - sorted.begin() << endl; // 输出:1

// 查找第一个>3的元素 auto ub = upper_bound(sorted.begin(), sorted.end(), 3); cout << "upper_bound index: " << ub - sorted.begin() << endl; // 输出:3 AI写代码

3.4 merge 合并两个已排序的范围到新容器(保持排序)

vector a = {1, 3, 5}; vector b = {2, 4, 6}; vector merged(a.size() + b.size());

// 合并a和b(均需已排序) merge(a.begin(), a.end(), b.begin(), b.end(), merged.begin()); // merged: [1,2,3,4,5,6] AI写代码 4、堆算法 STL提供了将范围作为堆来操作的算法,包括make_heap, push_heap, pop_heap, sort_heap等。

std::vector vec = {4, 1, 3, 2, 5}; std::make_heap(vec.begin(), vec.end()); // 构建最大堆,vec变为{5, 4, 3, 2, 1}

vec.push_back(6); std::push_heap(vec.begin(), vec.end()); // 将新元素加入堆,vec变为{6, 4, 5, 2, 1, 3}

std::pop_heap(vec.begin(), vec.end()); // 将最大元素移到末尾,vec变为{5, 4, 3, 2, 1, 6} int max_val = vec.back(); // 获取最大元素6 vec.pop_back(); // 移除最大元素

std::sort_heap(vec.begin(), vec.end()); // 将堆排序为升序序列,vec变为{1, 2, 3, 4, 5} AI写代码

5、最小/最大值算法 5.1 min 和 max 返回两个值或初始化列表中的最小/最大值

int a = 5, b = 3; int min_val = std::min(a, b); // 3 int max_val = std::max(a, b); // 5

auto min_of_list = std::min({4, 2, 8, 5, 1}); // 1 auto max_of_list = std::max({4, 2, 8, 5, 1}); // 8 AI写代码 5.2 min_element 和 max_element 返回范围内的最小/最大元素的迭代器

std::vector vec = {3, 1, 4, 2, 5}; auto min_it = std::min_element(vec.begin(), vec.end()); // 指向1 auto max_it = std::max_element(vec.begin(), vec.end()); // 指向5 AI写代码 5.3 minmax_element (C++11) 同时返回范围内的最小和最大元素的迭代器

std::vector vec = {3, 1, 4, 2, 5}; auto minmax = std::minmax_element(vec.begin(), vec.end()); // minmax.first指向1,minmax.second指向5 AI写代码 6、数值算法(在中) 6.1 accumulate 计算范围内元素的累加和(或自定义操作)

#include

std::vector vec = {1, 2, 3, 4, 5}; int sum = std::accumulate(vec.begin(), vec.end(), 0); // 和,初始值为0,结果为15 int product = std::accumulate(vec.begin(), vec.end(), 1, std::multiplies()); // 乘积,初始值为1,结果为120 AI写代码 6.2 inner_product 计算两个范围的内积(或自定义操作)

std::vector a = {1, 2, 3}; std::vector b = {4, 5, 6}; int dot = std::inner_product(a.begin(), a.end(), b.begin(), 0); // 14 + 25 + 3*6 = 32 AI写代码 6.3 iota 用连续递增的值填充范围

std::vector vec(5); std::iota(vec.begin(), vec.end(), 10); // 填充为10, 11, 12, 13, 14 AI写代码 6.4 partial_sum 计算部分和,将结果存储在目标范围内

std::vector src = {1, 2, 3, 4, 5}; std::vector dst(src.size()); std::partial_sum(src.begin(), src.end(), dst.begin()); // dst变为{1, 3, 6, 10, 15} AI写代码 6.5 adjacent_difference 计算相邻元素的差值,将结果存储在目标范围内

std::vector src = {1, 2, 3, 4, 5}; std::vector dst(src.size()); std::adjacent_difference(src.begin(), src.end(), dst.begin()); // dst变为{1, 1, 1, 1, 1} AI写代码 7、其他 7.1 generate 用生成函数填充范围

std::vector vec(5); int n = 0; std::generate(vec.begin(), vec.end(), &n { return n++; }); // 填充为0, 1, 2, 3, 4 AI写代码 7.2 generate_n 用生成函数填充范围的开始n个元素

std::vector vec(5); int n = 10; std::generate_n(vec.begin(), 3, &n { return n++; }); // 前三个元素为10, 11, 12,后两个保持不变 AI写代码 7.3 includes 检查一个排序范围是否包含另一个排序范围的所有元素

std::vector vec1 = {1, 2, 3, 4, 5}; std::vector vec2 = {2, 4}; bool includes = std::includes(vec1.begin(), vec1.end(), vec2.begin(), vec2.end()); // true AI写代码 7.3 set_union, set_intersection, set_difference, set_symmetric_difference 执行集合操作:并集、交集、差集和对称差集

std::vector v1 = {1, 2, 3, 4, 5}; std::vector v2 = {3, 4, 5, 6, 7}; std::vector result;

// 并集 std::set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(result)); // result为{1, 2, 3, 4, 5, 6, 7}

// 交集 result.clear(); std::set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(result)); // result为{3, 4, 5}

// 差集 (v1 - v2) result.clear(); std::set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(result)); // result为{1, 2}

// 对称差集 (v1 ∪ v2 - v1 ∩ v2) result.clear(); std::set_symmetric_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(result)); // result为{1, 2, 6, 7} AI写代码

8、常见问题 sort 与 stable_sort 的区别?

sort 采用快速排序(实际是 introsort 算法),不稳定(相等元素的相对位置可能改变),平均时间复杂度 O (n log n)。 stable_sort 采用归并排序,稳定(相等元素相对位置不变),时间复杂度 O (n log n),但空间开销略大。 为什么 remove 算法需要配合 erase 使用? remove 算法的原理是 “覆盖” 要删除的元素,将保留的元素移到前面,返回新的逻辑尾迭代器,但不修改容器的实际大小。erase 则通过迭代器范围真正删除元素,修改容器大小。因此需结合使用:container.erase(remove(...), container.end())。

哪些算法需要容器是已排序的? 二分查找系列(binary_search、lower_bound、upper_bound)、集合算法(set_intersection、set_union 等)、merge 等,这些算法依赖有序性实现高效操作(如二分查找 O (log n))。 ———————————————— 版权声明:本文为CSDN博主「Hgfdsaqwr」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/Hgfdsaqwr/article/details/156809238 https://infogram.com/9862pdf-1hnp27eqdjm7n4g https://infogram.com/9862pdf-1h0r6rzwyqpjl4e https://infogram.com/9862pdf-1h0n25opqjool4p https://infogram.com/9862pdf-1hxj48mqgjmn52v https://infogram.com/9862pdf-1h1749wqzjwjl2z https://infogram.com/9862pdf-1h9j6q759q7e54g https://infogram.com/9862pdf-1h984wv15gved2p https://infogram.com/9862pdf-1h0n25opqjkkl4p https://infogram.com/9862pdf-1h9j6q759q0pv4g https://infogram.com/9862pdf-1hnp27eqdjkxy4g

点赞
收藏
评论区
推荐文章
好买-葡萄 好买-葡萄
4年前
【数据结构与算法】—— 二分查找
1.二分查找的概念二分查找指的是在排好序的数组中,找到目标元素。如果元素存在则返回元素的下标,不存在则返回1.下面以升序为例进行简单描述2.查找过程:取数组中间元素与查找元素target比较。如果target等于中间元素则直接返回中间元素的下标,如果target小于数组中间元素则在数组左边查找,如果target大于数组中间元素则在右边查找。重复以上步骤。
九路 九路
5年前
7 二分搜索树的原理与Java源码实现
1折半查找法了解二叉查找树之前,先来看看折半查找法,也叫二分查找法在一个有序的整数数组中(假如是从小到大排序的),如果查找某个元素,返回元素的索引。如下:intarrnewint{1,3,4,6,8,9};在arr数组中查找6这个元素,查到返回对应的索引,没有找到就返回1思想很简单:1先找到数组中间元素ta
九路 九路
5年前
二分查找法的递归和非递归的实现
//二分查找法非递归实现,在一个有序的数组中查找e元素的位置,找不到返回1publicstaticintbinarySearch(intdata,inte){intl0;intrdata.length1;while(l<r){
Wesley13 Wesley13
4年前
Java Stream
1Stream简介Stream是数据渠道,用于操作数据源(集合,数组等)所生成得元素序列。而集合讲得是数据,流讲得是计算。注意:Stream自己不会存储元素。Stream不会改变源对象。相反,它会返回一个持有结果得新StreamStream操作时延迟执行得,这意味着它们会等到需要结果时才执
Stella981 Stella981
4年前
C++ 之获取map元素[转]
链接:https://www.cnblogs.com/jianfeifeng/p/11089799.html  对于map对象,count成员返回值只能是0或者1,map容器只允许一个键对应一个实例。所以count可有效地表明一个键是否存在。count返回出现的次数。  find返回指向元素的迭代器,如果元素不存在,则返回end迭代器。 
Wesley13 Wesley13
4年前
AWK 简明教程
AWK脚本的结构awk'BEGIN{print"start"}pattern{commands}END{print"end"}fileawk脚本通常由3部分组成。BEGIN,END和带模式匹配选项的常见语句块。这3个部分都是可选项,在脚本中可省略任意部分。AWK脚本
Wesley13 Wesley13
4年前
mysql 计算时间函数差
根据时间计算时间差函数TIMESTAMPDIFF(unit,begin,end)unit支持的单位有:MICROSECOND,SECOND,MINUTE,HOUR,DAY,WEEK,MONTH,QUARTER,YEAR.begin,end不需要相同的数据结构,可以存在一个为
Wesley13 Wesley13
4年前
MySQL 存储过程中执行DDL
一、定期增加表分区1、增加表分区例CREATEDEFINER\root\@\127.0.0.1\PROCEDURE\p\_create\_Partition\(INdatabaseNameVARCHAR(50),INtableNameVARCHAR(50))L\_END:BEGIN   DECLAREV\_
Stella981 Stella981
4年前
OpenCV访问像素点
三种方法迭代器创建一个Mat::Iterator对象it,通过itMat::begin()来的到迭代首地址,递增迭代器知道itMat::end()结束迭代;while(it!Scr.end<Vec3b()){//(it)00;//蓝色通道置零;
Wesley13 Wesley13
4年前
51nod 1318 最大公约数与最小公倍数方程组(2
题意给你$n$个元素,$m$个方程。每个方程形如$$\\begin{align}\\gcd(x\_i,y\_i)c\_i\\\\mathrm{lcm}(x\_i,y\_i)d\_i\\end{align}$$之类的形式。询问这个方程组是否有解。有$T$组数据。$1\\leT\\le10,1\