码迷,mamicode.com
首页 > 其他好文 > 详细

二叉树的迭代器

时间:2015-01-15 15:43:14      阅读:227      评论:0      收藏:0      [点我收藏+]

标签:

仅有遍历算法是不够的,在许多应用中,我们还需要对遍历本身进行抽象。假如有一个求和的函数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;
    }
};

二叉树的迭代器

标签:

原文地址:http://www.cnblogs.com/roy-mustango/p/4226249.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!