迭代器¶
map<string, Person *> :: iterator a;
a就是map
迭代器¶
迭代器是一种常见的设计方法。
迭代器一般情况下都是和容器联合一起使用的,通过迭代器把容器里的数据一个一个的读取,迭代器提供了一种方便的方法接口。一个不落的读取。
迭代器一般都是只读的,读取查看,并不会删除修改堆栈里的数据。堆栈里的数据没有发生任何改变。
堆栈没有迭代器的话,想要查看数据不删除的话就没有办法,因为pop会删除,peak只能查看最上面的。就只能使用迭代器。
C++ 有很多容器(堆栈,树),每一个容器都有一个迭代器。
迭代器实现¶
迭代器和容器是分开的。¶
把迭代器放到容器的内部,一个容器有一个迭代器。做成一个类中类。类中的类迭代器的名称小写。
容器增加两个成员函数,begin和end。
- begin 返回一个迭代器,指向容器第一个对象的地址
- end 返回一个迭代器,指向的是容器最后一个数据的后面一个的位置。也就是堆栈的栈顶。终止哨兵,它这个位置没有数据,前一个位置才有数据。
加上头文件保护,做成模版。¶
不要一上来就做成模版,那样太复杂。先做好一个不是模版的,再修改成模版的。
各种各样的数据都可以存堆栈。
迭代器像一个指针。
下面的例子比较简单,数组大小是固定的。
更好的是把数组大小做成动态的增大,C++有做好的动态数组。
也可以做成链表,也比较灵活。
代码实现:
//更好的迭代器 做成模版
template<class T, int ssize = 100>//容量100
class Stack
{
T stack[ssize];//内部是一个数据
int top;//栈顶
public:
Stack() : top(0) {}//栈顶设置为0
void push(const T& i)//数据压入堆栈 引用类型
{
//如果堆栈满了,就不做执行
stack[top++] = i;
}
T pop()//从堆栈取数据
{
//堆栈不能是空的,空的就取不了
return stack[--top]; //top没有数据,所以需要--
}
//迭代器要操作堆栈里面的数据
//要做成友元类
class iterator;
friend class iterator;
//堆栈的迭代器
//迭代器要做的像灵巧指针 使用迭代器的时候像一个指针 可以++ ++是对index进行的操作,索引的操作又是对堆栈内部的数组的操作,数组也是用下标进行操作的。
//类中类 第一个字母小写
class iterator
{
//迭代器要操作堆栈里面的数据
//要做成友元类
//迭代器对堆栈进行操作,通过构造函数把堆栈传递进来。
Stack& s;
//索引 迭代器使用的
int index;
public:
//通过构造函数把堆栈传递进来,通过迭代器内部的s保存
iterator(Stack& is) : s(is), index(0) {}
iterator(Stack& is, bool) : s(is), index(s.top) {}
//运算符重载
//返回迭代器位置的数据
//T current() const { return s.stack[index];}
//current可以写的更好,如下面的 *运算符重载
//这样迭代器更像是一个指针 通过*直接取值
T operator*() const {return s.stack[index]; }
//运算符重载。因为指针有++
//迭代器++的时候,都会从容器中读一个数据出来。迭代器像一个指针,++就会读取下一个数据。
//前++
T operator++()
{
//容器里没有数据,就不能读了。
return s.stack[++index];//从堆栈内部的数组里取数据出来。数据都是保存在数组里的。
}
//后++
T operator++(int)
{
//容器里没有数据,就不能读了。
return s.stack[index++];
}
//+=运算符重载,返回一个迭代器
iterator& operator+=(int amount)
{
index += amount;
return *this;
}
//== 和!= 运算符重载
bool operator==(const iterator& rv) const
{
return index == rv.index;
}
bool operator!=(const iterator& rv) const
{
return index != rv.index;
}
};
//增加功能
iterator begin()//begin也是C++的标准做法
{
return iterator(*this);//返回一个迭代器
}
iterator end()//end也是C++的标准做法
{
return iterator(*this,true);//返回一个迭代器
}
//输出流操作符重载
friend std::ostream& operator<<(std::ostream& os, const iterator& it)
{
return os << it.current();
}
};
调试:
//测试
void test() {
Stack<int> s;
s.push(10);
s.push(20);
s.push(30);
s.push(40);
s.push(50);
s.push(60);
//使用迭代器 读取数据
//类中类
//IntStackIter it(s);//把堆栈传给迭代器
Stack<int>::iterator it = s.begin();//把堆栈传给迭代器
while (it != s.end()) {
std::cout << it++ << std::endl; //移动迭代器
}
Stack<int>::iterator start = s.begin();
//+=运算符重载
start += 2;
//读取当前数据
std::cout << *start << std::endl;
//不用迭代器也可以读取,但是pop是把数据都删除了。
//迭代器是读取查看,并不会改变堆栈里的数据。堆栈里的数据没有发生任何改变。
//迭代器一般都是只读的。并不会删除修改。
//堆栈没有迭代器的话,想要查看数据不删除的话就没有办法,因为pop回删除,peak只能查看最上面的。就只能使用迭代器。
for (int i = 0; i < 6; i++) {
std::cout << s.pop() << std::endl;
}
}