美文网首页
C++: 使用Iterator遍历二叉树

C++: 使用Iterator遍历二叉树

作者: 赵伯舟 | 来源:发表于2018-08-17 23:43 被阅读1次

    上篇文章中我们实现了一个泛型的Find函数,并实现了支持这个泛型函数的链表Iterator, 这次,我们来实现支持这个函数的二叉树Iterator:

    定义二叉树节点

    template <typename T>
    class tree_node
    {
    public:
        T value;
        tree_node* left;
        tree_node* right;
    
        explicit tree_node(T t=0)
        {
            value = t;
            left = nullptr;
            right = nullptr;
        }
    
        bool operator == (const T t) const
        {
            return value == t;
        }
        bool operator == (const tree_node& n) const
        {
            return this->value == n.value;
        }
        bool operator != (const T t) const
        {
            return value != t;
        }
        bool operator != (const tree_node& n) const
        {
            return this->value != n.value;
        }
    };
    

    同样,定义了一个模板类作为二叉树的节点

    二叉树Iterator基类

    由于二叉树有先序,中序,后序三种遍历方式,所以我们可以定义一个基类,声明好接口:

    template <typename node>
    class tree_iterator
    {
    protected:
        node* curr_ptr;
        node* root_ptr;
        std::stack<node*> st;
    
    public:
        tree_iterator()
        {
            curr_ptr = nullptr;
            root_ptr = nullptr;
        }
        explicit tree_iterator(node* ptr)
        {
            curr_ptr = ptr;
            root_ptr = ptr;
        }
    
        virtual tree_iterator<node>& operator ++() = 0;
    
        tree_iterator<node>& operator ++(int)
        {
            return operator++();
        }
    
        node& operator * ()
        {
            return *curr_ptr;
        }
    
        node* operator -> ()
        {
            return curr_ptr;
        }
    
        node* get() const
        {
            return curr_ptr;
        }
    
        const node& operator * () const
        {
            return curr_ptr->value;
        }
    
        bool operator == (const tree_iterator& src)
        {
            return curr_ptr == src.get();
        }
    
        bool operator != (const tree_iterator& src)
        {
            return curr_ptr != src.get();
        }
    };
    

    上面的tree_iterator实现了基本的接口,但是把重载++声明为纯虚函数,下放给子类去实现

    三种遍历方式

    不同的遍历Iterator只需要实现不同的++即可

    1.先序遍历
    template <typename node>
    class pre_order_tree_iterator : public tree_iterator<node>
    {
    public:
        using tree_iterator<node>::operator++;
    
        explicit pre_order_tree_iterator(node* p = nullptr) : tree_iterator<node>(p)
        {
            if(p)
                this->st.push(p);
    
            operator++();
        }
    
        tree_iterator<node> &operator++() override
        {
            auto& st = this->st;
            auto& curr_ptr = this->curr_ptr;
    
            if(st.empty())
                curr_ptr = nullptr;
            else
            {
                curr_ptr = st.top();
                st.pop();
                if (curr_ptr->right)
                    st.push(curr_ptr->right);
                if(curr_ptr->left)
                    st.push(curr_ptr->left);
            }
            return *this;
        }
    };
    
    2.中序遍历
    template <typename node>
    class in_order_tree_iterator : public tree_iterator<node>
    {
    public:
        using tree_iterator<node>::operator++;
        using tree_iterator<node>::st;
        using tree_iterator<node>::curr_ptr;
    
        explicit in_order_tree_iterator(node* p = nullptr) : tree_iterator<node>(p)
        {
            if(curr_ptr)
            {
                while (curr_ptr)
                {
                    st.push(curr_ptr);
                    curr_ptr = curr_ptr->left;
                }
                if(!st.empty())
                {
                    curr_ptr = st.top();
                    st.pop();
                }
            }
        }
    
        tree_iterator<node> &operator++() override
        {
            if(curr_ptr->right)
            {
                curr_ptr = curr_ptr->right;
                while(curr_ptr)
                {
                    st.push(curr_ptr);
                    curr_ptr = curr_ptr->left;
                }
    
            }
            if(!st.empty())
            {
                curr_ptr = st.top();
                st.pop();
            }
            else
                curr_ptr = nullptr;
            return *this;
        }
    };
    
    3.后序遍历
    template <typename node>
    class pos_order_tree_iterator : public tree_iterator<node>
    {
    public:
        using tree_iterator<node>::operator++;
        using tree_iterator<node>::st;
        using tree_iterator<node>::curr_ptr;
    
        explicit pos_order_tree_iterator(node* p = nullptr) : tree_iterator<node>(p)
        {
            if(curr_ptr)
            {
                while (curr_ptr)
                {
                    st.push(curr_ptr);
                    if(curr_ptr->right)
                        st.push(curr_ptr->right);
                    curr_ptr = curr_ptr->left;
                }
                if(!st.empty())
                {
                    curr_ptr = st.top();
                    st.pop();
                }
            }
        }
    
        tree_iterator<node> &operator++() override
        {
            if(!st.empty())
            {
                if(st.top()->right == curr_ptr)/// 遍历过
                {
                    curr_ptr = st.top();
                    st.pop();
                }
                else/// 未遍历过
                {
                    curr_ptr = st.top();
                    st.pop();
                    while(curr_ptr)
                    {
                        st.push(curr_ptr);
                        if(curr_ptr->right)
                            st.push(curr_ptr->right);
                        curr_ptr = curr_ptr->left;
                    }
                    curr_ptr = st.top();
                    st.pop();
                }
            }
            else
                curr_ptr = nullptr;
            return *this;
        }
    };
    

    测试

    int main()
    {
        auto n1 = new tree_node<int>(1);
        auto n2 = new tree_node<int>(2);
        auto n3 = new tree_node<int>(3);
        auto n4 = new tree_node<int>(4);
        auto n5 = new tree_node<int>(5);
    
        n1->left = n2;
        n1->right = n3;
    
        n2->left = n4;
        n2->right = n5;
    
        auto res = Find(pos_order_tree_iterator<tree_node<int>>(n1),
                         pos_order_tree_iterator<tree_node<int>>(),
                         1);
    
        if (res.get())
            cout << res->value << endl;
        else
            cout << "Not Found" << endl;
    
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:C++: 使用Iterator遍历二叉树

          本文链接:https://www.haomeiwen.com/subject/rlrxiftx.html