C++ 中的迭代算法

在 C++ 中,迭代算法(Iterative Algorithms)是指通过循环结构(如 forwhiledo-while)实现重复计算的算法,其核心是利用迭代器(Iterator)或直接操作容器元素,逐步更新状态直至满足终止条件。C++ 的迭代算法广泛应用于容器遍历、搜索、排序、数值计算等场景,结合标准模板库(STL)中的容器和算法,可实现高效、简洁的代码。以下从迭代器基础、常见迭代算法、实现技巧及示例等方面详细介绍。

一、C++ 迭代器(Iterator)基础

迭代器是 C++ 中用于遍历容器元素的 “指针类” 对象,提供了统一的接口访问不同容器(如 vectorlistmap 等)的数据。迭代器支持的操作包括:

  • *it:解引用,访问当前元素。
  • it++/it--:移动到下一 / 前一元素(根据容器特性,可能是双向或单向移动)。
  • it == other_it/it != other_it:判断是否指向同一位置。
1. 迭代器类型
  • 正向迭代器(Forward Iterator):只能单向移动(如 list<T>::iterator)。
  • 双向迭代器(Bidirectional Iterator):支持前后移动(如 vector<T>::iterator)。
  • 随机访问迭代器(Random Access Iterator):支持跳跃式移动(如 vector<T>::iterator,类似指针运算 it + n)。
2. 常用容器的迭代器获取

#include <vector>
#include <list>
#include <map>

int main() {
    // vector(随机访问迭代器)
    std::vector<int> vec = {1, 2, 3};
    std::vector<int>::iterator vec_it = vec.begin(); // 指向首元素
    std::vector<int>::iterator vec_end = vec.end();   // 指向尾后位置(不包含)

    // list(双向迭代器)
    std::list<std::string> lst = {"a", "b", "c"};
    auto lst_it = lst.begin(); // C++11 可使用 auto 自动推导类型

    // map(双向迭代器,键值对为 pair<const Key, Value>)
    std::map<int, std::string> m = {{1, "one"}, {2, "two"}};
    for (auto it = m.begin(); it != m.end(); ++it) {
        std::cout << it->first << ": " << it->second << std::endl; // 访问键值对
    }

    return 0;
}

二、C++ 中常见的迭代算法

C++ 的 STL 提供了大量基于迭代器的算法(定义在 <algorithm> 头文件中),可分为遍历、查找、排序、修改、数值计算等类别。以下是典型示例:

1. 遍历算法:for_each
  • 功能:对容器中的每个元素执行指定操作。
  • 原型template <class InputIt, class UnaryFunction> UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f);
  • #include <algorithm>
    #include <vector>
    #include <iostream>
    
    void print(int x) {
        std::cout << x << " ";
    }
    
    int main() {
        std::vector<int> vec = {10, 20, 30};
        std::for_each(vec.begin(), vec.end(), print); // 输出:10 20 30
        return 0;
    }
    

    C++11 Lambda 表达式简化写法

    std::for_each(vec.begin(), vec.end(), [](int x) { std::cout << x << " "; });
    
2. 查找算法:find 和 find_if
  • find:查找等于给定值的元素。

    #include <algorithm>
    #include <vector>
    #include <iostream>
    
    int main() {
        std::vector<int> vec = {1, 3, 5, 7};
        auto it = std::find(vec.begin(), vec.end(), 5); // 查找值为 5 的元素
        if (it != vec.end()) {
            std::cout << "Found at index: " << (it - vec.begin()) << std::endl; // 输出索引 2
        }
        return 0;
    }
    
  • find_if:按条件查找元素(通过谓词函数判断)。

    // 查找第一个大于 4 的元素
    auto it = std::find_if(vec.begin(), vec.end(), [](int x) { return x > 4; });
    
3. 排序算法:sort
  • 功能:对容器元素排序(默认升序,可自定义比较规则)。
  • 原型template <class RandomAccessIterator> void sort(RandomAccessIterator first, RandomAccessIterator last);
  • 示例:对 vector 降序排序:

    #include <algorithm>
    #include <vector>
    #include <iostream>
    
    bool compare(int a, int b) {
        return a > b; // 降序
    }
    
    int main() {
        std::vector<int> vec = {3, 1, 4, 2};
        std::sort(vec.begin(), vec.end(), compare); // 传入比较函数
        // 或用 Lambda:std::sort(vec.begin(), vec.end(), [](int a, int b){ return a > b; });
        for (int x : vec) { // C++11 范围 for 循环
            std::cout << x << " "; // 输出:4 3 2 1
        }
        return 0;
    }
    
4. 数值计算:accumulate
  • 功能:对容器元素求和(或自定义累加操作)。
  • 原型template <class InputIt, class T> T accumulate(InputIt first, InputIt last, T init);
  • 示例:计算 vector 元素之和:

    #include <numeric> // accumulate 头文件
    #include <vector>
    #include <iostream>
    
    int main() {
        std::vector<int> vec = {1, 2, 3, 4};
        int sum = std::accumulate(vec.begin(), vec.end(), 0); // 初始值为 0
        std::cout << "Sum: " << sum << std::endl; // 输出:10
        return 0;
    }
    
5. 自定义迭代算法:实现斐波那契数列

通过迭代而非递归计算斐波那契数列,避免栈溢出且效率更高。

#include <iostream>

int fibonacci(int n) {
    if (n <= 0) return 0;
    if (n == 1) return 1;
    int a = 0, b = 1, c;
    for (int i = 2; i <= n; ++i) {
        c = a + b;
        a = b;
        b = c; // 迭代更新状态
    }
    return b;
}

int main() {
    std::cout << "Fibonacci(10): " << fibonacci(10) << std::endl; // 输出 55
    return 0;
}

三、迭代算法的实现技巧

1. 利用范围 for 循环(C++11+)

简化容器遍历,隐藏迭代器细节:

std::vector<int> vec = {1, 2, 3};
for (int x : vec) { // 自动遍历所有元素
    std::cout << x << " ";
}
2. 逆向迭代器(Reverse Iterator)

从容器尾部向头部遍历:

std::vector<int> vec = {1, 2, 3};
for (auto it = vec.rbegin(); it != vec.rend(); ++it) { // rbegin() 指向尾元素,rend() 指向头前位置
    std::cout << *it << " "; // 输出:3 2 1
}
3. 迭代器失效问题
  • 场景:当容器结构改变(如插入、删除元素)时,原有迭代器可能失效(即不再指向有效元素)。
  • 解决方案
    • 对 vector/deque,插入 / 删除操作后,位于操作点之后的迭代器失效。
    • 对 list/map/set,仅当前操作的迭代器失效,其他迭代器保持有效。
    std::vector<int> vec = {1, 2, 3, 4};
    auto it = vec.begin() + 1; // 指向元素 2
    vec.erase(vec.begin());    // 删除首元素,it 失效(因 vector 内存重新分配)
    // 正确做法:erase 返回新的有效迭代器
    it = vec.erase(vec.begin()); // it 指向新的首元素(原元素 2)
    
4. 结合 Lambda 表达式

用 Lambda 简化谓词函数或操作逻辑,提高代码简洁性:

// 筛选偶数并存储到新容器
std::vector<int> vec = {1, 2, 3, 4};
std::vector<int> even;
std::copy_if(vec.begin(), vec.end(), std::back_inserter(even), [](int x) {
    return x % 2 == 0; // Lambda 作为条件判断
});

四、迭代与递归的性能对比(C++ 场景)

以计算斐波那契数为例:

方法时间复杂度空间复杂度C++ 实现风险
递归O(2n)O(n)栈溢出(n 较大时)
迭代O(n)O(1)

递归实现(低效且危险)

int fib_recursive(int n) {
    if (n <= 1) return n;
    return fib_recursive(n-1) + fib_recursive(n-2); // 重复计算子问题
}

迭代实现(高效稳定)

int fib_iterative(int n) { /* 见前文示例 */ }

五、总结

C++ 中的迭代算法通过迭代器和循环结构实现,具有高效、可控的特点,尤其在结合 STL 算法时能大幅简化代码。掌握迭代器的类型、容器特性及迭代失效问题,是写出健壮 C++ 代码的关键。实际开发中,优先使用迭代而非递归(除非问题天然适合递归,如树的遍历),以避免栈溢出并提升性能。

核心要点

  • 迭代器是遍历容器的通用工具,需根据容器类型选择合适的迭代器(如随机访问、双向)。
  • STL 算法(如 for_eachsort)基于迭代器设计,需熟练掌握其用法。
  • 注意迭代器失效问题,避免访问无效指针
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值