数据结构二叉树遍历(前中后,递归非递归)

Posted zhao111222333444

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构二叉树遍历(前中后,递归非递归)相关的知识,希望对你有一定的参考价值。

这里写目录标题

前序

递归

class Solution 
public:
    vector<int> v;
    vector<int> preorderTraversal(TreeNode* root) 
        //vector不能写在函数里,否则只会输出最后一个节点
        if(root==nullptr)return v;
        v.push_back(root->val);
        if(root->left)
            preorderTraversal(root->left);//注意没有return
        if(root->right)
            preorderTraversal(root->right);
            return v;
    
;

非递归

先入根节点(为了一开始不为空进入循环)
栈顶出栈,并记录内容,
当前结点的右结点入栈
当前结点的左结点入栈
当栈不为空时重复上述过程。

class Solution 
public:
    vector<int> preorderTraversal(TreeNode* root) 
        vector<int> v;
        if(root==nullptr)return v;
        stack<TreeNode*> s;
        s.push(root);
        while(!s.empty())
            TreeNode* node=s.top();
            v.push_back(node->val);
            s.pop();
            if(node->right)//注意前序是根,左,右
            //所以保证左在右的前面,右先入栈
                s.push(node->right);
            if(node->left)
                s.push(node->left);
        
        return v;
    
;

中序遍历

递归

class Solution 
public:
    vector<int> v;
    vector<int> inorderTraversal(TreeNode* root) 
        if(root==nullptr)return v;
        if(root->left)
            inorderTraversal(root->left);
        v.push_back(root->val);
        if(root->right)
            inorderTraversal(root->right);
        return v;
    
;

非递归

根节点开始循环入栈左节点到没有为止,此时出栈顶(最左节点),并记录左节点,如果有右节点,就标记一个右节点为根节点。
等到下一次循环把这个节点作为根节点走1的遍历。如果没有这个节点就从栈顶取作为根节点再次循环1.
特殊:栈为空并且跟为空才可以结束循环

思路:
还是用栈辅助来做
1.root每次都去找当前所在位置的最左节点,然后出栈记录
2.按照左中右的规律,此时不能出中(此时的栈顶),要看它是否有左节点,走1的循环,每次找到最左节点时,root都指向了nullptr。
3.这里可以看到结束条件有两个:栈为空,root(node)为空。这是因为中序遍历优中后右的特性,会有一个时刻栈为空但右结点并未被遍历(最开始的根都出去了,在出去之前node指向了最初根的右节点,不是空),因此只有在curr也为空证明右结点不存在的情况下,才能结束遍历。

class Solution 
public:
    vector<int> inorderTraversal(TreeNode* root) 
        vector<int> v;
        if(root==nullptr)return v;
        stack<TreeNode*> s;
        TreeNode* node=root;
        while(node!=nullptr||!s.empty())
            //while(node->left)每次循环在找到最左节点时node一定是空
            while(node)
                s.push(node);
                node=node->left;
            
            TreeNode* top=s.top();
            v.push_back(top->val);
            s.pop();
            if(top->right)
                node=top->right;
              
        
        return v;
    
;

后序遍历

递归

class Solution 
public:
    vector<int> v;//递归每次都会走函数的全体,所以写外面
    vector<int> postorderTraversal(TreeNode* root) 
        if(root==nullptr)return v;
        if(root->left)
            postorderTraversal(root->left);
        if(root->right)
            postorderTraversal(root->right);
        v.push_back(root->val);
        return v;
    
;

非递归

1.首先根节点开始一直入栈左节点到空,此时不能出因为可能要有右节点(右在根前),此时判断是否有节点为空或者是否访问过这个右节点了,就读节点,出栈,记录前一个节点
如果有右节点并且没有访问,此时root就是栈顶的右节点。

1.先访问最左节点
2.先看看最左节点有没有右节点,有的话就去访问,把右节点当root再次访问它的最左,如果没有的话这个就可以删除了。

法1:

class Solution 
public:
    vector<int> postorderTraversal(TreeNode* root) 
        vector<int> v;
        if(root==nullptr)return v;
        stack<TreeNode*> s;
        TreeNode* prev;
        while(root||!s.empty())
            while(root)
                s.push(root);
                root=root->left;
            
            TreeNode* mtop=s.top();
            //先找到最左子树
            //此时还不能删,可能有右子树
            //没有的话就删
            if(mtop->right==nullptr||mtop->right==prev)
                v.push_back(mtop->val);
                s.pop();
                prev=mtop;//这是当前访问节点
            
            //有的话先访问右子树
            else
            //访问右子树
                if(mtop->right)
                    root=mtop->right;
                
            
        
        return v;
    
;

法2利用前序辅助:

class Solution 
public:
    vector<int> postorderTraversal(TreeNode* root) 
        stack<TreeNode*> t;
        vector<int> v;
        if(root==nullptr)return v;
        stack<TreeNode*> s;
        s.push(root);
        while(!s.empty())
            TreeNode* node=s.top();
            //v.push_back(node->val);
            //另一个栈保存就好了,vector里不用
            s.pop();
            t.push(node);
            if(node->left)
            //注意改变了左和右
                s.push(node->left);
            if(node->right)
                s.push(node->right);
        
        
        while(!t.empty())
            v.push_back(t.top()->val);
            t.pop();
        
        return v;
    
;

以上是关于数据结构二叉树遍历(前中后,递归非递归)的主要内容,如果未能解决你的问题,请参考以下文章

二叉树的前中后序遍历(非递归实现)

二叉树的前中后序遍历的非递归解法

二叉树的前中后序遍历的非递归解法

非递归实现二叉树的前中后序遍历

二叉树的前中后序非递归法

二叉树的前中后序非递归法