C++结合二分法分析迭代器的使用和运算(参考书籍C++primer第五版)

使用迭代器

//迭代器是访问string对象的字符、vector对象的元素及其他容器元素的一种机制,所有标准库容器都可以使用迭代器,适用范围大于下标运算符
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <fstream>
using namespace::std;
int main()
{
	//获取迭代器和指针不同,不使用取地址符,而是有迭代器的类型同时拥有返回迭代器的成员
	//例如名为begin的成员负责返回指向第一个元素的迭代器
	//名为end的成员负责返回指向容器(或string对象)“尾元素的下一个位置”的迭代器,这个迭代器指示的是容器的一个本不存在的“尾后”元素,简称尾后迭代器
	//如果容器为空,begin和end返回的是同一个迭代器,都是尾后迭代器
	vector<string> ss(10, "an");
	auto b = ss.begin();
	auto e = ss.end();

	//迭代器运算符
	//*iter            返回迭代器iter所指元素的引用
	//iter->mem        解引用iter并获取该元素名为mem的成员,等价于(*iter).mem
	//++iter           令iter指示容器的下一个元素
	//--iter           令iter指示容器的上一个元素
	//iter1 == iter2   判断两个迭代器是否相等,如果指示的是同一个元素或者都是同一个容器尾后迭代器则相等
	//iter1 != iter2

	//把string对象的第一个字母改成大写形式
	string s = "some string";
	if (s.begin() != s.end())//确保s非空
	{
		auto it = s.begin();
		*it = toupper(*it);
	}

	//将迭代器从一个元素移动到另外一个元素,++,--
	//注意,尾后迭代器并不实际指示某个元素,所以不能对其进行递增或解引用操作

	//把string对象的第一个单词改写为大写形式
	for (auto it = s.begin(); it != s.end() && !isspace(*it); ++it)
		*it = toupper(*it);

	//迭代器的类型
	//我们无需知道迭代器的精确类型,就像string和vector的size_type成员到底是什么类型一样
	vector<int>::iterator it;//it1可以读写
	string::iterator it2;//it2可以读写
	vector<int>::const_iterator it3;//it3只能读元素
	string::const_iterator it4;//it4只能读元素

	//begin和end运算符
	//begin和end返回的具体类型由对象是否是常量决定,是常量,const_iterator,不是常量,iterator
	//有些时候我们只需对对象进行读操作,C++11引入了cbegin()和cend()专门得到const_iterator,无论对象是否是常量
	auto it5 = s.cbegin();

	//结合解引用和成员访问操作
	//解引用迭代器可以获得迭代器所指的对象,如果该对象的类型是类,我们可能需要进一步访问它的成员
	(*it).empty();//正确
	*it.empty();//错误,想要访问it的名为empty的成员,但it是迭代器,并没有empty成员
	//为了简化上述表达式,C++定义了箭头运算符->,把解引用和成员访问两个操作结合在了一起
	it->empty();//等价于(*it).empty


	//把文本文件text.txt读入容器text
	ifstream in("text.txt");
	vector<string> text;
	for (string a; in >> a;)
		text.push_back(a);

	//依次输入text的每一行直至遇到第一个空白行为止
	for (auto it = text.cbegin();
		it != text.cend() && !it->empty();
		++it)
		cout << *it << endl;

	//某些对vector对象的操作会使迭代器失效
	//vector对象可以动态的增长,但已知有两个限制
	//不能在范围for循环中向vector对象添加元素
	//任何改变vector容量的操作都有可能使该vector对象的迭代器失效
}

迭代器的运算

#include <iostream>
#include <string>
#include <vector>
#include <cctype>
#include <fstream>
using namespace::std;
int main()
{
	//iter + n         结果仍然是迭代器,迭代器指示的位置与原来相比向前移动了n个位置,结果最多到尾元素的下一个位置
	//iter - n         同上,向后移动n个位置
	//iter += n        将iter+n的结果赋给iter
	//iter -= n        同上
	//iter1 - iter2    结果是它们之间的距离,类型是名为difference_type的带符号整型数
	//> >= < <=        关系运算符,位置在前的迭代器>位置在后的迭代器

	//计算得到最接近vi中间元素的一个迭代器,它指向某vector对象中间位置的元素
	//auto mid = vi.begin() + vi.size() / 2;
	//处理vi前半部分元素
	//if(it < mid){}

	
	//使用迭代器进行二分搜索
	//beg和end表示搜索范围
	auto beg = text.begin(), end = text.end();
	auto mid = text.begin() + (end - beg) / 2;//初始状态下的中间点
	//当元素尚未检查并且没找到smile时执行循环
	int i = 0;
	while (mid != end && *mid != sought) {
		if (sought < *mid)     //我们要找的元素在后半部分
			end = mid;         //调整搜索范围忽略后半部分
		else                   //我们要找的元素在前半部分
			beg = mid + 1;     //在mid之后搜索
		mid = beg + (end - beg) / 2;//新的中间点
	}
	
	

}

练习

#include <iostream>
#include <string>
#include <vector>
#include <cctype>
#include <fstream>
using namespace::std;
int main()
{
	//练习3.24 使用迭代器重做下列练习
	练习3.20 读入一组整数并存入一个vector对象,输出每对相邻整数的和
	//vector<int> ive;
	//int i;
	//while (cin >> i)
	//	ive.push_back(i);
	//  for (i = 0; i < ive.size()-1; ++i)
	//	cout << ive[i] + ive[i + 1] << " " ;*/
	//	//改写程序,输出第1个和最后1个元素的和,第2个和倒数第2个元素的和,以此类推
	//for (i = 0; i < ive.size() / 2; ++i)
	//	cout << ive[i] + ive[ive.size() - 1 - i] << " ";
	//if (ive.size() % 2)
	//	cout << 2 * ive[ive.size() / 2];
	vector<int> ive;
	int i;
	while (cin >> i)
		ive.push_back(i);
	//输出每对相邻整数的和
	for (auto it = ive.begin(); it != ive.end(); ++it)
		cout << *it + *(it + 1) << " ";
	//输出第1个和最后1个元素的和,第2个和倒数第2个元素的和,以此类推
	auto beg = ive.begin(), end = ive.end();
	auto mid = beg + (end - beg) / 2;
	while (beg <= mid && end >= mid) {
		cout << *beg + *end << " ";
	}

	//练习3.25 使用迭代器重写下面程序
	//vector<unsigned> scores(11, 0);
	//unsigned grade;
	//while (cin >> grade) {
	//	if (grade <= 100)//这里确认输入是否合理十分重要
	//		++scores[grade / 10];//笔者觉得这很精妙简洁
	//}
	//for (auto c : scores)
	//	cout << c << " ";
	vector<unsigned> rank(11, 0);//11个等级
	unsigned grade;
	while (cin >> grade)
		if (grade <= 100)
			(*(rank.begin() + grade / 10))++;
	//输出
	for (auto it = rank.begin(); it != rank.end(); ++it)
		cout << *it << endl;

	//练习3.26 二分搜索程序中,为什么用的是 mid = beg + (end - beg) / 2, 而非 mid = (beg + end) / 2 ; ?
	//因为迭代器之间支持的运算只有’-’,而没有’+’。end-beg指相距若干元素,将它除以2之后与beg相加,表示移动到一beg与end中间的位置。
	
	


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值