经典算法学习——非递归遍历二叉树

       我们知道二叉树是一种递归定义的数据结构,包括二叉树的创建、遍历、求树高、叶子节点个数等等。使用递归来进行以上操作非常的简便,相关实现请参考 《C语言实现二叉树的基本操作》。但是今天我们剑走偏锋,使用非递归的方式来实现树的先序、中序、后序遍历。实现代码上传至 https://github.com/chenyufeng1991/TraverseBinaryTreeNoRecursion  。

(1)非递归实现先序遍历

在非递归的三种遍历中,先序遍历是最简单的。思路如下:首先把根节点入栈,并且在根节点出栈的时候访问根节点;同时判断根节点的右子树是否为空,若不为空,则右孩子入栈;判断根节点的左孩子是否为空,若不为空,则左孩子入栈。当栈不为空时,重复以上操作。

核心代码如下:

void PreOrderNoRecursion(Node *node, stack<Node *> &sta)
{
    while (!sta.empty())
    {
        Node *temp = sta.top();
        cout << temp->data << " ";

        sta.pop();
        if (temp->rChild != NULL)
        {
            sta.push(temp->rChild);
        }

        if (temp->lChild != NULL)
        {
            sta.push(temp->lChild);
        }
    }
    return;
}

(2)非递归实现中序遍历

思路如下:首先根节点入栈,判断根节点的左孩子是否为空,若不为空,则左孩子入栈,并不断移动node指针指向左孩子,直到左孩子节点为空。

然后弹出栈顶元素并访问该元素,判断弹出元素的右孩子是否为空,若不为空,则把右孩子入栈,并把node指针指向右孩子。重复以上操作。

核心代码如下:

void MidOrderNoRecursion(Node *node, stack<Node *>&sta)
{
    while (!sta.empty())
    {
        while (node->lChild != NULL)
        {
            sta.push(node->lChild);
            node = node->lChild;
        }

        Node *temp = sta.top();
        cout << temp->data << " ";
        sta.pop();
        if (temp->rChild != NULL)
        {
            sta.push(temp->rChild);
            node = temp->rChild;
        }
    }
}


(3)非递归实现后序遍历

后续遍历是这三种遍历中最麻烦的,需要在节点的结构体中再加入一个参数isVisited,表示某个节点是否被访问过。思路如下:首先根节点入栈,然后判断左孩子是否为空,若不为空,则左孩子入栈,并移动node到左孩子,直到左孩子为空。然后判断栈顶元素,如果栈顶元素没有右孩子或者右孩子已经被访问过,那么就访问该栈顶元素,并出栈;如果栈顶元素有右孩子并且右孩子没有被访问过,那么把右孩子入栈,把node指针指向右孩子。

核心代码如下:

void PostOrderNoRecursion(Node *node, stack<Node *>&sta)
{
    while (!sta.empty())
    {
        while (node->lChild != NULL)
        {
            sta.push(node->lChild);
            node = node->lChild;
        }

        Node *temp = sta.top();
        if (temp->rChild == NULL || temp->rChild->isVisited == true)
        {
            cout << temp->data << " ";
            temp->isVisited = true;
            sta.pop();
        }
        else if(temp->rChild != NULL && temp->isVisited == false)
        {
            sta.push(temp->rChild);
            node = temp->rChild;
        }
    }
}


测试代码如下:

int main(int argc, const char * argv[])
{
    cout << "请输入二叉树的节点,输入-1结束:";
    Node *node;
    CreateBinaryTree(&node);

    cout << "非递归先序遍历的结果为:";
    stack<Node *> nodeStack;
    // 首先根节点入栈
    nodeStack.push(node);
    PreOrderNoRecursion(node, nodeStack);
    cout << endl;

    cout << "非递归中序遍历的结果为:";
    stack<Node *> nodeStackM;
    // 首先根节点入栈
    nodeStackM.push(node);
    MidOrderNoRecursion(node, nodeStackM);
    cout << endl;

    cout << "非递归后序遍历的结果为:";
    stack<Node *> nodeStackP;
    // 首先根节点入栈
    nodeStackP.push(node);
    PostOrderNoRecursion(node, nodeStackP);
    cout << endl;

    return 0;
}


你可能感兴趣的:(遍历,二叉树)