开发者

C++构建缓存加速的实现示例

目录
  • 1、非修改序列算法
    • 1.1 find 和 find_if
    • 1.2 count 和 count_if
    • 1.3 for_each
    • 1.4 equal 与 mismatch
    • 1.5 all_of, any_of, none_of
  • 2、修改序列算法
    • 2.1 copy 和 copy_if
    • 2.2 transform
    • 2.3 replace、replace_if与 replace_copy
    • 2.4 remove、remove_if 与 erase
    • 2.5 unique
    • 2.6 reverse
    • 2.7 rotate
    • 2.8 shuffle
  • 3、排序和相关算法
    • 3.1 sort、stable_sort 与 partial_sort
    • 3.2 nth_element
    • 3.3 binary_search、lower_bound、upper_bound
    • 3.4 merge
  • 4、堆算法
    • 5、最小/最大值算法
      • 5.1 min 和 max
      • 5.2 min_element 和 max_element
      • 5.3 minmax_element (C++11)
    • 6、数值算法(在<numeric>中)
      • 6.1 accumulate
      • 6.2 inner_product
      • 6.3 iota
      • 6.4 partial_sum
      • 6.5 adjacent_difference
    • 7、其他
      • 7.1 generate
      • 7.2 generate_n
      • 7.3 includes
      • 7.3 set_union, set_intersection, set_difference, set_symmetric_difference
    • 8、常见问题

      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<int> 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<int> 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
      }

      1.2 count 和 count_if

      • count(begin, end, value):统计等于 value 的元素个数。
      • count_if(begin, end, predicate):统计满足谓词(predicate)的元素个数。
      std::vector<int> 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

      1.3 for_each

      对范围内的每个元素应用一个函数

      std::vector<int> vec = {1, 2, 3, 4, 5};
      std::for_each(vec.begin(), vec.end(), [](int& x) { 
          x *= 2; // 将每个元素乘以2
      });
      // 现在vec变为{2, 4, 6, 8, 10}

      1.4 equal 与 mismatch

      • equal(b1, e1, b2):判断两个范围 [b1,e1) 和 [b2, b2+(e1-b1)) 是否相等。
      • mismatch(b1, e1, b2):返回两个范围中第一个不相等元素的迭代器对(pair)。
      vector<int> a = {1, 2, 3};
      vector<int> b = {1, 2, 4};
      vector<int> 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元素相等)
      }

      1.5 all_of, any_of, none_of

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

      std::vector<int> 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

      2、修改序列算法

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

      2.1 copy 和 copy_if

      • copy(begin, end, dest):将 [begin, end) 中的元素复制到 dest 开始的位置。
      • copy_if(begin, end, dest, predicate):复制满足谓词的元素到 dest。
      vector<int> src = {1, 2, 3, 4, 5};
      vector<int> dest(5);  // 需预先分配足够空间
       
      // 复制所有元素
      copy(src.begin(), src.end(), dest.begin());  // dest: [1,2,3,4,5]
       
      // 复制偶数元素到新容器
      vector<int> evens;
      copy_if(src.begin(), src.end(), back_inserter(evens), [](int x) {
          return x % 2 == 0;
      });  // evens: [2,4]

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

      2.2 transform

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

      vector<int> nums = {1, 2, 3};
      vector<int> squares(3);
       
      // 计算平方(单参数转换)
      transform(nums.begin(), nums.end(), squares.begin(), [](int x) {
          return x * x;
      });  // squares: [1,4,9]
       
      // 两容器元素相加(双参数转换)
      vector<int> a = {1, 2, 3};
      vector<int> b = {4, 5, 6};
      vector<int> sum(3);
      transform(a.begin(), a.end(), b.begin(), sum.begin(), [](int x, int y) {
          return x + y;
      });  // sum: [5,7,9]

      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<int> nums = {1, 2, 3, 2, 5};
       
      // 替换所有2为20
      repl编程客栈ace(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<int> res;
      replace_copy(nums.begin(), nums.end(), back_inserter(res), 3, 300);  // res: [1,0,300,0,5]

      2.4 remove、remove_if 与 erase

      • remove(begin, end, value):将等于 value 的元素 “移动” 到容器末尾,返回新的逻辑尾迭代器(不实际删除元素,需配合 erase)。
      • remove_if(begin, end, predicate):移动满足谓词的元素到末尾。
      vector<int> 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]

      2.5 unique

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

      std::vector<int> 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}

      2.6 reverse

      反转范围内的元素顺序

      std::vector<int> vec = {1, 2, 3, 4, 5};
      std::reverse(vec.begin(), vec.end()); // vec变为{5, 4, 3, 2, 1}

      2.7 rotate

      旋转范围内的元素,使中间元素成为新的第一个元素

      std::vector<int> vec = {1, 2, 3, 4, 5};
      std::rotate(vec.begin(), vec.begin() + 2, vec.end()); // 以3为起点旋转,vec变为{3, 4, 5, 1, 2}

      2.8 shuffle

      随机重排范围内的元素(需要C++11或更高版本)

      #include <random>
      #include <algorithm>
       
      std::vector<int> vec = {1, 2, 3, 4, 5};
      std::random_device rd;
      std::mt19937 g(rd());
      std::shuffle(vec.begin(), vec.end(), g); // 随机打乱vec中的元素

      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<int> 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<int>()); // 降序,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<int> 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

      3.2 nth_element

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

      std::vector<int> vec = {5, 3, 1, 4, 2, 6};
      // 找到第三小的元素(索引2)
      std::nth_element(vec.begin(), vec.begin() + 2, vec.end());
      // 现在vec[2]是3,它左边的元素<=3,右边的>=3

      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<int> 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

      3.4 merge

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

      vector<int> a = {1, 3, 5};
      vector<int> b = {2, 4, 6};
      vector<int> 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]

      4、堆算法

      STL提供了将范围作为堆来操作的算法,包括make_heappush_heappop_heapsort_heap等。

      std::vector<int> 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}

      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

      5.2 min_element 和 max_element

      返回范围内的最小/最大元素的迭代器

      std::vector&http://www.devze.comlt;int> 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

      5.3 minmax_element (C++11)

      同时返回范围内的最小和最大元素的迭代器

      std::vector<int> vec = {3, 1, 4, 2, 5};
      auto minmax = std::minmax_element(vec.begin(), vec.end());
      // minmax.first指向1,minmax.second指向5

      6、数值算法(在<numeric>中)

      6.1 accumulate

      计算范围内元素的累加和(或自定义操作)

      #include <numeric>
       
      std::vector<int> vec = {1, 2, 3, 4, 5};
      int sum = std::accumulate(vec.begin(), vec.end(), 0); // 和,初始值为0,结果为15
      int product = std::accumulate(vec.begin(), vecwww.devze.com.end(), 1, std::multiplies<int>()); // 乘积,初始值为1,结果为120

      6.2 inner_product

      计算两个范围的内积(或自定义操作)

      std::vector<int> a = {1, 2, 3};
      std::vector<int> b = {4, 5, 6};
      int dot = std::inner_product(a.begin(), a.end(), b.begin(), 0); // 1*4 + 2*5 + 3*6 = 32

      6.3 iota

      用连续递增的值填充范围

      std::vector<int> vec(5);
      std::iota(vec.begin(), vec.end(), 10); // 填充为10, 11, 12, 13, 14

      6.4 partial_sum

      计算部分和,将结果存储在目标范围内

      std::vector<int> src = {1, 2, 3, 4, 5};
      std::vector<int> dst(src.size());
      std::partial_sum(src.begin(), src.end(), dst.begin()); // dst变为{1, 3, 6, 10, 15}

      6.5 adjacent_difference

      计算相邻元素的差值,将结果存储在目标范围内

      std::vector&lwww.devze.comt;int> src = {1, 2, 3, 4, 5};
      std::vector<int> dst(src.size());
      std::adjacent_difference(src.begin(), src.end(), dst.begin()); // dst变为{1, 1, 1, 1, 1}

      7、其他

      7.1 generate

      用生成函数填充范围

      std::vector<int> vec(5);
      int n = 0;
      std::generate(vec.begin(), vec.end(), [&n]() { 
          return n++; 
      }); // 填充为0, 1, 2, 3, 4

      7.2 generate_n

      用生成函数填充范围的开始n个元素

      std::vector<int> vec(5);
      int n = 10;
      std::generate_n(vec.begin(), 3, [&n]() { 
          return n++; 
      }); // 前三个元素为10, 11, 12,后两个保持不变

      7.3 includes

      检查一个排序范围是否包含另一个排序范围的所有元素

      std::vector<int> vec1 = {1, 2, 3, 4, 5};
      std::vector<int> vec2 = {2, 4};
      bool includes = std::includes(vec1.begin(), vec1.end(), vec2.begin(), vec2.end()); // true

      7.3 set_union, set_intersection, set_difference, set_symmetric_difference

      执行集合操作:并集、交集、差集和对称差集

      std::vector<int> v1 = {1, 2, 3, 4, 5};
      std::vector<int> v2 = {3, 4, 5, 6, 7};
      std::vector<int> 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}

      8、常见问题

      1. sort 与 stable_sort 的区别?

        • sort 采用快速排序(实际是 introsort 算法),不稳定(相等元素的相对位置可能改变),平均时间复杂度 O (n log n)。
        • stable_sort 采用归并排序,稳定(相等元素相对位置不变),时间复杂度 O (n log n),但空间开销略大。
      2. 为什么 remove 算法需要配合 erase 使用?

        remove 算法的原理是 “覆盖” 要删除的元素,将保留的元素移到前面,返回新的逻辑尾迭代器,但不修改容器的实际大小。erase 则通过迭代器范围真正删除元素,修改容器大小。因此需结合使用:container.erase(remove(...), container.end())。

      3. 哪些算法需要容器是已排序的?

        二分查找系列(binary_search、lower_bound、upper_bound)、集合算法(set_intersection、set_union 等)、merge 等,这些算法依赖有序性实现高效操作(如二分查找 O (log n))。

      到此这篇关于C++构建缓存加速的实现示例的文章就介绍到这了,更多相关C++构建缓存加速内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

      0

      上一篇:

      下一篇:

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      最新开发

      开发排行榜