【LeetCode】Binary Tree Preorder &Inorder & Postorder Traversal

本文详细介绍了二叉树的三种遍历方式:先序、中序和后序遍历,包括递归和非递归实现方法。通过具体代码示例,帮助读者理解和掌握这些算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先序遍历


递归方法:
这个方法简单,只要按照 自己-> 右儿子 -> 左儿子的顺序就可以了

非递归法,开始时根结点在栈中,然后
{
栈顶输弹出
如果有右儿子,右儿子入栈
如果有左儿子,左儿子入栈
}
这样循环,直到栈为空。栈顶一直是下一个要打印的根结点。

#if METHOD == 1
/*
这里对vector的使用方法要得当,把两个vector拼在一起的方法是
把out1,out2,拼成(out1,out2) 
out2.insert(out2.begin(),out1.begin(),out1.end());//out1,out2顺序不要弄错 
*/
class Solution {
public:
    vector<int> preorderTraversal(TreeNode *root) {//中左右 
        vector<int> out;
        if(root == NULL)
        	return out;
        	
        vector<int> out1 = preorderTraversal(root->left);
        vector<int> out2 = preorderTraversal(root->right);        
        
        out.insert(out.begin(),out2.begin(),out2.end());	//右 
        out.insert(out.begin(),out1.begin(),out1.end());	//左 
        out.insert(out.begin(),root->val); 					//中 
        
        return out;
    }
};
#elif METHOD == 2
//堆栈方法 
//这个方法不太好理解,需要加以研究 
class Solution {
public:
    vector<int> preorderTraversal(TreeNode *root) {
        vector<int> out;
        if(root == NULL)
        	return out;
       	//TreeNode *head = root;					//就是记录上一个弹出的结点 
       	treenodeStack.push(root);
        while(!treenodeStack.empty())
		{
			TreeNode *cur = treenodeStack.top();//增加一个记录点
			treenodeStack.pop();
			out.push_back(cur->val);
		
			if(cur->right != NULL)	treenodeStack.push(cur->right)/*,printf("lpush = %d\n",cur->right->val)*/;
			if(cur->left != NULL)	treenodeStack.push(cur->left)/*,printf("rpush = %d\n",cur->left->val)*/;
		} 
        return out;
    }
private:
	stack<TreeNode*> treenodeStack; 
};
#endif


中序遍历


中序遍历二叉树:
递归法,不多说,左孩子-》自己-》右孩子这样递归就可以了。

循环法:使用栈,下面的代码还是比较好的。
其中指针p的使用非常关键
#if 0
class Solution {
public://中序遍历,左中右 
    vector<int> inorderTraversal(TreeNode *root) {
		vector<int> out;
        if(root == NULL)      	return out;
        	
        vector<int> outleft = inorderTraversal(root->left);	
        vector<int> outright = inorderTraversal(root->right);
		out.insert(out.begin(),outright.begin(),outright.end());		
		out.insert(out.begin(),root->val);	
		out.insert(out.begin(),outleft.begin(),outleft.end());
        return out;
    }
};
#elif 1//栈 ------------赞!!!! 
class Solution {
public://中序遍历,左中右 
    vector<int> inorderTraversal(TreeNode *root) {
		vector<int> out;
        stack<TreeNode *> stk;
       	TreeNode *p = root;
       	while(!stk.empty() || p)
       	{
       		if(p != NULL)
       		{
       			stk.push(p);
       			p = p->left;
  			}
  			else
  			{
				p = stk.top();
				stk.pop();
				out.push_back(p->val);
				p = p->right;
  			}
  		}
       
        return out;
    }
};
#endif 


后序遍历


递归方法:
这个方法简单,只要按照左儿子 -> 右儿子 -> 自己的顺序就可以了

非递归方法1:
相比于前序遍历,后续遍历思维上难度要大些,前序遍历是通过一个stack,首先压入父亲结点,然后弹出父亲结点,并输出它的value,之后压人其右儿子,左儿子即可。然而后序遍历结点的访问顺序是:左儿子 -> 右儿子 -> 自己。那么一个结点需要两种情况下才能够输出:第一,它已经是叶子结点;第二,它不是叶子结点,但是它的儿子已经输出过(代码里非递归方法head就是用来记录访问过的儿子的)。那么基于此我们只需要记录一下当前输出的结点即可。对于一个新的结点,如果它不是叶子结点,儿子也没有访问,那么就需要将它的右儿子,左儿子压入。如果它满足输出条件,则输出它,并记录下当前输出结点。输出在stack为空时结束。



非递归方法2:

利用堆栈很按后序的逆序输入再做一次逆序

从一开始,就按 自己->右儿子->左儿子顺序输出,最后做一下逆序就好

#if METHOD == 1
/*
这里对vector的使用方法要得当,把两个vector拼在一起的方法是
把out1,out2,拼成(out1,out2) 
out2.insert(out2.begin(),out1.begin(),out1.end());//out1,out2顺序不要弄错 
*/
class Solution {
public:
    vector<int> postorderTraversal(TreeNode *root) {
        vector<int> out;
        if(root == NULL)
        	return out;
        
        vector<int> out1 = postorderTraversal(root->left);
        vector<int> out2 = postorderTraversal(root->right);
        
        out.insert(out.begin(),root->val); 					//中 
        out.insert(out.begin(),out2.begin(),out2.end());	//右 
        out.insert(out.begin(),out1.begin(),out1.end());	//左 
        return out;
    }
};
#elif METHOD == 2
//堆栈方法 
//这个方法不太好理解,需要加以研究 
class Solution {
public:
    vector<int> postorderTraversal(TreeNode *root) {
        vector<int> out;
        if(root == NULL)
        	return out;
       	TreeNode *head = root;					//就是记录上一个弹出的结点 
       	treenodeStack.push(root);
        while(!treenodeStack.empty())
		{
			TreeNode *cur = treenodeStack.top();//增加一个记录点
			
			if(cur->left == head || cur->right== head ||(cur->left == NULL && cur->right == NULL))//这个条件很关键 
			{
				treenodeStack.pop();
				out.push_back(cur->val);
				head = cur;
				//printf("pop = %d\n",cur->val);
				//system("pause");
			} 
			else
			{
				if(cur->right != NULL)	treenodeStack.push(cur->right)/*,printf("lpush = %d\n",cur->right->val)*/;
				if(cur->left != NULL)	treenodeStack.push(cur->left)/*,printf("rpush = %d\n",cur->left->val)*/;
			}
		} 
        return out;
    }
private:
	stack<TreeNode*> treenodeStack; 
};
#elif METHOD == 3
/*
这个方法赞呀!自己->右儿子->左儿子顺序输出,最后做一下逆序就好 
*/
class Solution {
public:
    vector<int> postorderTraversal(TreeNode *root) {
        vector<int> res;
        if(root == NULL)
            return res;
        vector<TreeNode*> stc;
        stc.push_back(root);
        while(!stc.empty()) {
            TreeNode* node = stc.back();
            res.push_back(node->val);
            stc.pop_back();
            if(node->left != NULL) {
                stc.push_back(node->left);
            }
            if(node->right != NULL) {
                stc.push_back(node->right);
            }
        }
        reverse(res.begin(), res.end());
        return res;
    }
}; 
#endif




                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值