跳转至

迭代器

map<string, Person *> :: iterator  a;

a就是map 字典类型 键是string类型 值是Person类型 注: string和Person *可以修改的。

迭代器

迭代器是一种常见的设计方法。

迭代器一般情况下都是和容器联合一起使用的,通过迭代器把容器里的数据一个一个的读取,迭代器提供了一种方便的方法接口。一个不落的读取。

迭代器一般都是只读的,读取查看,并不会删除修改堆栈里的数据。堆栈里的数据没有发生任何改变。

堆栈没有迭代器的话,想要查看数据不删除的话就没有办法,因为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;
    }

}