• 二叉树遍历


    二叉树遍历最简单的就是递归了。因为递归实质上是栈存了一些中间值,所以我们可以使用stack实现迭代版的遍历。

    • 中序遍历

    步骤:

    首先将root节点作为当前节点。

    1.如果当前节点不为空,压入当前节点。将左节点作为当前节点。

    2.否则弹出栈顶节点作为当前节点,输出当前节点。

    3.如果右节点不为空,右节点作为当前节点。

    4.否则将当前节点置为空。

    重复1、2、3、4直到栈为空。

    void InorderTraversal(TreeNode *root){
        if(!root)return;
        TreeNode *node=root;
        stack<TreeNode*> mystk;
        while(node||mystk.size()){
            while(node){
                mystk.push(node);
                node=node->left;
            }   
            node=mystk.top();
            mystk.pop();
            cout<<node->val<<'	';
            if(node->right){
                node=node->right;
            }else{
                node=NULL;
            }   
       }   
    }
    • 前序遍历

    前序遍历和中序遍历差不多,只是输出节点值的时机不同。

    步骤:

    以root节点作为当前节点

    1.如果当前节点不为空,将当前节点压入栈,同时输出当前节点。并将左节点作为当前节点。

    2.否则弹出栈顶作为当前节点。

    3.如果右节点不为空,将右节点作为当前节点。

    4.否则将当前节点置为空。

    重复1、2、3、4直到栈为空。

    void PreorderTraversal(TreeNode *root){
    
        if(!root)return;
        TreeNode *node=root;
        stack<TreeNode*> mystk;
        while(node||mystk.size()){
            while(node){
                mystk.push(node);
                cout<<node->val<<'	';
                node=node->left;
            }
            node=mystk.top();
            mystk.pop();
            if(node->right){
                node=node->right;
            }else{
                node=NULL;
            }
       }
    }
    • 后序遍历

    后序遍历有点特殊,需要一个辅助节点记录是否遍历过了。

    步骤:

    将root节点作为当前节点

    1.如果当前节点不为空,将当前节点压入栈中。将左节点作为当前节点。

    2.否则,将栈顶节点(不弹出)作为当前节点。

    3.如果右节点不为空且右节点不等于pre节点,将右节点作为当前节点。

    4.否则,输出当前节点,pop栈顶,并将当前节点作为pre节点。设置当前节点为空。

    重复1、2、3、4直到栈为空。

    void PostorderTraversal(TreeNode *root){
        if(!root)return;
        TreeNode *node=root;
        TreeNode *pre=NULL;
        stack<TreeNode*> mystk;
        while(node||mystk.size()){
            while(node){
                mystk.push(node);
                node=node->left;
            }
            node=mystk.top();
            if(node->right&&node->right!=pre){
                node=node->right;
            }else{
                cout<<node->val<<'	';
                mystk.pop();
                pre=node;
                node=NULL;
            }
       }
    }

    上述三种遍历对于每个节点都是入栈一次出栈一次,所以时间复杂度和空间复杂度都是o(n)。

    而Morris遍历则可以o(1)完成各种遍历。下面解释morris遍历。

    • Morris遍历

    morris遍历的精髓是提出了前驱节点的概念:即输出前驱节点后,下一个输出的就是当前节点。

    参考http://blog.csdn.net/zhaoyunfullmetal/article/details/48087663

  • 相关阅读:
    Java数据结构之栈(Stack)
    Java数据结构之单向环形链表(解决Josephu约瑟夫环问题)
    Java数据结构之双向链表
    zookeeper:JavaApi操作节点
    zookeeper:3
    单例模式
    zookeeper:2
    架构版本
    zookeeper:1
    Java反射
  • 原文地址:https://www.cnblogs.com/coderht/p/7652797.html
Copyright © 2020-2023  润新知