使用递归和非递归遍历二叉树

2017-07-09 20:42:55

遍历二叉树的主流方法有三种,分别是前序遍历,中序遍历,后序遍历。

通常使用递归的算法进行遍历,这种遍历的代码编写简单,容易实现。不过,函数递归使用的函数栈,所以,一般这样的问题都可以用自定义的栈来替代递归函数。

1、前序遍历

前序遍历是指中间节点优先于左右两个子节点输出,所以使用递归的算法为:

void preorder(Bintree* root)
{
    if (root==NULL) return ;
    else
    {
        cout<<(char)root->data<<" ";
        preorder(root->left);
        preorder(root->right);
    }
}

如果使用非递归方法,则需要申请一个栈来保存数据。

首先,先将中间节点压入栈中,后将右节点和左节点压入栈中。这一步是保证左节点先于右节点输出。

每次弹出栈的顶部数据,将该数据输出,同时将该节点的右节点和左节点压入栈中。

循环处理,直到栈为空。

void preorder2(Bintree* root)
{
    stack<Bintree*> s;
    if(root) s.push(root);
    while(!s.empty())
    {
        Bintree* cur=s.top();
        s.pop();
        if(cur->right) s.push(cur->right);
        if(cur->left) s.push(cur->left);
        cout<<(char)cur->data<<" ";
    }
}

2、中序遍历

中序遍历是指先将左边的节点输出后再输出自身,最后输出右节点。使用递归的方法来实现的代码如下:

void inorder(Bintree* root)
{
    if(root)
    {
        inorder(root->left);
        cout<<root->data<<" ";
        inorder(root->right);
    }
}

如果采用非递归的话,则有点麻烦。首先,中序的要求是需要将左边输出完毕后再输出自身,所以需要一直向左寻找,直到左边的节点为空,则输出当前的栈顶元素。

具体算法过程如下:

首先申请一个栈s,将当前的cur设置为root,如果栈非空或者cur非NULL,则一直循环操作。

如果cur非空,将cur压入栈中,同时,cur更新为cur的left值,

如果cur为空,将栈顶元素弹出并输出,将栈顶元素的右值赋值给cur,继续下次的循环。

void inorder2(Bintree* root)
{
    Bintree* cur=root;
    stack<Bintree*> s;
    while(!s.empty()||cur)
    {
        if(cur)
        {
            s.push(cur);
            cur=cur->left;
        }
        else
        {
            Bintree* temp=s.top();
            s.pop();
            cur=temp->right;
            cout<<temp->data<<" ";
        }
    }
}

3、后序遍历

显然,后序遍历的意思就是指,中间的节点在最后输出,用递归可以很形象的表现出来。

void postorder(Bintree* root)
{
    if(root)
    {
        postorder(root->left);
        postorder(root->right);
        cout<<root->data<<" ";
    }
}

倘若使用非递归,则会有点麻烦。我们可以使用两个栈来完成这项工作。

首先,将root压入s1中,当栈1非空的时候,一直循环。

将栈顶的元素出栈,将其左右节点入栈,同时所有从s1中弹出的元素都将压入s2中。

最后将s2中的元素全部输出即可。

void postorder2(Bintree* root)
{
    stack<Bintree*> s1;
    stack<Bintree*> s2;
    s1.push(root);
    while(!s1.empty())
    {
        Bintree* cur=s1.top();
        s1.pop();
        s2.push(cur);
        if(cur->left) s1.push(cur->left);
        if(cur->right) s1.push(cur->right);
    }
    while(!s2.empty())
    {
        cout<<s2.top()->data<<" ";
        s2.pop();
    }
}
原文地址:https://www.cnblogs.com/hyserendipity/p/7143195.html