二叉树迭代器

一. 简介

仅有遍历算法是不够的,在许多应用中,我们还需要对遍历本身进行抽象。假如有一个求和的函数sum,我们希望它能应用于链表,数组,二叉树等等不同的数据结构。这时,我们可以抽象出迭代器(Iterator)的概念,通过迭代器把算法和数据结构解耦了,使得通用算法能应用于不同类型的数据结构。

我们可以把sum函数定义成:

int sum(Iterator from, Iterator to)

链表作为一种线性结构,它的迭代器实现非常简单和直观,而二叉树的迭代器实现则不那么容易,我们不能直接将递归遍历转换为迭代器。究其原因,这是因为二叉树递归遍历过程是编译器在调用栈上自动进行的,程序员对这个过程缺乏足够的控制。既然如此,那么我们如果可以自己来控制整个调用栈的进栈和出栈不是就达到控制的目的了吗?

先看看二叉树的非递归遍历方法:

后序遍历:

 

void PostOrder_Nonrecursive(Node* T)
{    
    stack<Node*> s1 , s2;    
    Node* curr ;           // 指向当前要检查的节点  
    s1.push(T);  
    while(!s1.empty())  // 栈空时结束    
    {  
        curr = s1.top();  
        s1.pop();  
        s2.push(curr);  
        if(curr->lchild)  
            s1.push(curr->lchild);  
        if(curr->rchild)  
            s1.push(curr->rchild);  
    }  
    while(!s2.empty())  
    {  
        printf("%c ", s2.top()->data);  
        s2.pop();  
    }  
}

 

中序遍历:

 

void InOrderTraverse1(Node* T)   // 中序遍历的非递归  
{  
    if(!T)  
        return ;  
    Node* curr = T;    // 指向当前要检查的节点  
    stack<Node*> s;
    while(curr != NULL || !s.empty())
    {
        while(curr != NULL)
        {
            s.push(curr);
            curr = curr->lchild;
        }//while
        if(!s.empty())
        {
            curr = s.top();
            s.pop();
            cout<<curr->data<<"  ";
            curr = curr->rchild;
        }
    }
}

 

先序遍历

 

void PreOrder_Nonrecursive(Node* T)     //先序遍历的非递归    
{  
    if(!T)    
        return ;    
    
    stack<Node*> s;  
    s.push(T);  
  
    while(!s.empty())  
    {  
        Node* temp = s.top();  
        cout<<temp->data<<" ";  
        s.pop();  
        if(temp->rchild)  
            s.push(temp->rchild);  
        if(temp->lchild)  
            s.push(temp->lchild);  
    }  
}

 

二. 迭代器接口

 

typedef stack<AVLNode*> Stack;
typedef queue<AVLNode*> Queue;

extern class AVLTree;
class AVLIterator
{
protected:
    AVLNode* now;
    Stack s;
public:
    virtual AVLIterator& operator++() = 0;
    AVLIterator& operator++(int){ return operator++(); }
    AVLNode& operator*() { return *now; }
    const AVLNode& operator*() const { return *now; }
    virtual void dfs(AVLNode* root) = 0;
    bool operator==(const AVLIterator& src) const { return now == src.now; }
    bool operator!=(const AVLIterator& src) const { return now != src.now; }
};

 

虽然是给AVL树写的, 但是同样适用于所有二叉树

三. 先序遍历迭代器

 

class PreorderIterator :public AVLIterator
{
protected:
    void dfs(AVLNode* root) {/*什么也不做*/}
public:
    PreorderIterator(AVLNode* root) :AVLIterator()
    {
        s = Stack();
        s.push(root);
        operator++();
    }
    PreorderIterator() :AVLIterator(){ now = 0; }

    PreorderIterator& operator++()
    {
        if (s.empty())
            now = NULL;
        else
        {
            now = s.top();
            s.pop();
            // 注意入栈顺序
            if (now->right)
                s.push(now->right);
            if (now->left)
                s.push(now->left);
        }
        return *this;
    }
};

 

四. 中序遍历迭代器

 

class InorderIterator :public AVLIterator
{
protected:
    void dfs(AVLNode* v)
    {
        while (v)
        {
            s.push(v);
            v = v->left;
        }
    }
public:
    // 初始化中序迭代器. 迭代器的初始位置是树的最左结点.
    InorderIterator(AVLNode* root) :AVLIterator()
    {
        s = Stack();
        dfs(root);
        operator++();
    }
    InorderIterator():AVLIterator(){ now = 0; }

    //@Override
    InorderIterator& operator++()
    {
        if (s.empty())
        {
            now = 0;
        }
        else 
        {
            // 找到当前结点(栈顶)
            now = s.top();
            s.pop();
            // 为下一次移动做准备: 
            // 模拟中序遍历的入栈方式
            // 对右子树的左侧路径进行深搜, 并记录左侧路径
            if (now->right != 0)
                dfs(now->right);
        }
        return *this;
    }
};

五. 后序遍历迭代器

class PostorderIterator :public AVLIterator
{
protected:
    AVLNode* _right; //记忆已经访问过的右子树
    Stack s2;
    void dfs(AVLNode* n)
    {
        while (!s.empty())
        {
            AVLNode* curr = s.top();
            s.pop();
            s2.push(curr);
            if (curr->left)
                s.push(curr->left);
            if (curr->right)
                s.push(curr->right);
        }
    }
public:
    PostorderIterator(){ now = 0; }
    PostorderIterator(AVLNode* root)
    {
        s2 = Stack();
        s.push(root);
        dfs(0);
        operator++();
    }

    PostorderIterator& operator++()
    {
        if (s2.empty())
            now = 0;
        else {
            now = s2.top();
            s2.pop();
        }
        return *this;
    }
};

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值