迭代器基础和使用

1.迭代器简介


什么是迭代器
  • 是一种检查容器内元素并遍历元素的数据类型
迭代器的主要功能
  • 其主要功能是来访问标准库中容器的元素
  • 字符串可以使用迭代器,可以近似把字符串看作是字符的容器
  • 迭代器有有效和无效之分

2. 使用迭代器
begin和end

  • begin表示获得指向第一个元素的迭代器
    • svec不包含任何元素,空vector 
  • end表示获得最后一个元素的下一个位置的迭代器
    •  返回一个根本不存在的尾部元素
    •  通常称为尾后迭代器,或者尾迭代器
  •  迭代器可以使用auto来定义begin和end变量

迭代器运算

  •  获得指向的元素本身
    • 通过使用解引用迭代器来获取,与指针类似 (*item)  
    • 注意不要尝试使用解引用来获得尾迭代器
    • 使用的时候要判断容器是否为空,这个与索引使用类似  
迭代器的移动
  • 使用++或者--来一定迭代器
    • 在移动的过程中要注意其范围,判断其是否到了end就无法移动了

迭代器的类型

  • 总体上就两个大类
    • 非常量迭代器 vector<int>::iterator it
      • 可读可写    
      • 如果容器的对象时非常量是可以使用iterator 或者 const_iterator
    • 常量迭代器  vector<int>::const_iterator it
      • 只能读不能写  
      • 如果容器的对象时常量是只能使用 const_iterator
  • cbegin 和 cend
    • 可以同时使用在上面的两种迭代器,只是最终的类型不同而已
      •     vector<int> v ; auto  it1 = v.begin();
      •     const vector<int> cv; auto it2 = cv.begin();  
    • cbegin 就表示只是使用了 const_iterator;
      •     vector<int> v ; auto  it1 = v.cbegin();

解引用来访问具体元素

  • 解引用的格式 (*it)以及成员访问
    • (*it).empty()
    • *it.empty()  
    • 以上两个是本质的区别的
  • 成员访问简化(->)
    • (*it).empty()     
    • it->empty()
    • 以上两个是一样的,以后要经常使用后者  

迭代器失效

  • 不能在范围for循环中向vector对象添加元素
  • 任何一种可能改变vector对象容器的操作,都会是该vector对象的迭代器失效


实例练习:
  1. 尝试获得尾迭代器的值
  2. 利用迭代器修改第一个字符为大写
  3. 利用迭代器修改第一个词为大写
  4. 对比 (*it).empty() 和 *it.empty()  
  5. 迭代器类型的实例

     
     
  1. #pragma region begin end迭代器
  2. //迭代器begin和end是两个关键的位置元素
  3. //尤其end并不是最后一个元素,而是最后一个元素后面的一个位置,并不是元素
  4. vector<int> ivec{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  5. auto ibegin = ivec.begin();
  6. auto iend = ivec.end();
  7. cout << "begin =" << *ibegin << endl;
  8. //cout << "end =" << (int)*iend << endl; //会报错,因为最后一个没有任何东西
  9. #pragma endregion
  10. #pragma region 访问并修改string为大写
  11. //这里尤其要注意如何使用迭代器来访问和修改元素
  12. string s = "my name is wall-e";
  13. auto sbegin = s.begin();
  14. auto send = s.end();
  15. if (isalpha(*sbegin) && sbegin != send)
  16. {
  17. *sbegin = toupper(*sbegin);
  18. }
  19. cout << s << endl;
  20. #pragma endregion
  21. #pragma region 访问并修改string第一个词和全部为大写
  22. string s1 = "my name is wall-e";
  23. string::iterator it = s1.begin();
  24. string::iterator send1 = s1.end();
  25. while (isalpha(*it) && it != send1 && !isspace(*it))
  26. {
  27. *it = toupper(*it);
  28. ++it;
  29. }
  30. cout << s1 << endl;
  31. while (it != send1)
  32. {
  33. *it = toupper(*it);
  34. ++it;
  35. }
  36. cout << s1 << endl;
  37. #pragma endregion
  38. #pragma region 常量迭代器类型的实例
  39. //if (ivec > svec); //err 无法比较两个不同的类型
  40. vector<int> ivec2{ 1, 2, 3, 4, 5, 6 };
  41. const vector<int> ivec3{ 1, 2, 3, 4, 5, 6 };
  42. //ivec3.push_back(7); //无法添加新元素
  43. //*ivec3.begin() = 7; //无法修改其元素的值
  44. //只能使用const_iterator来定义
  45. vector<int>::const_iterator constBegin = ivec3.begin();
  46. //vector<int>::iterator testBegin = ivec3.begin(); //无法使用普通迭代器来获取
  47. //对于普通的vector容器是可以使用常量和非常量迭代来获取
  48. vector<int>::const_iterator constbegin = ivec2.begin();
  49. vector<int>::iterator testBegin = ivec2.begin();
  50. #pragma endregion


3.迭代器运算(vector, string)


  • 所有的标准容器包括vector,string等
    • 支持++,--移动运算
    • 也可以使用==、!=进行比较
  • vector,string还包括
    • 每一移动跨过多个元素
    • 迭代器之间关系运算
 
迭代器算术运算
  • 计算中间位置的迭代器
    • auto min = vi.begin() + vi.size() / 2;
  • 判断两个迭代器前后位置<, >,>=,<=
  • 两个迭代器最差运算 it1 - it2
    • 返回值为difference_type类型,其为带符号的整数

利用迭代器实现二分搜索算法
  • 二分法是在一个有序的序列中使用的
  • 算法步骤
    • 先从中间位置搜索,如果中间位置是要找的值则停止
    • 中间位置不符合,则比较他们之间的大小
      • 如果中间位置大于要找的值,则在前半部分查找,  
      • 如果中间位置小于要找的值,则在后半部分查找,

实例练习:
  1. 二分法算法

      
      
  1. // 查询11的位置
  2. vector< int> ivecS{ 1, 3, 5, 7, 9, 11,13 };
  3. auto beginS = ivecS.begin();
  4. auto midS = beginS + ivecS.size() / 2;
  5. auto endS = ivecS.end();
  6. while (*midS != 11)
  7. {
  8. if (*midS > 11)
  9. {
  10. beginS = midS+1;
  11. }
  12. else
  13. {
  14. endS = midS;
  15. }
  16. midS = beginS + (endS - beginS) / 2;
  17. }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值