二叉树的前序、中序、后序遍历(递归和非递归)

一.二叉树的数据结构:

struct TreeNode {
     int val;
     TreeNode *left;
     TreeNode *right;
     TreeNode() 
     	: val(0), left(nullptr), right(nullptr)
     {}
     TreeNode(int x)
     	: val(x), left(nullptr), right(nullptr) 
     {}
     TreeNode(int x, TreeNode *left, TreeNode *right) 
        : val(x), left(left), right(right) 
     {}
  };

二.递归遍历

1.前序

void preOrder(TreeNode* root)
{
	if (root)
	{
		cout << root->val << " ";
		preOrder(root->left);
		preOrder(root->right);
	}
	cout<<endl;
}

2.中序

void inOrder(TreeNode* root)
{
	if (root)
	{
		inOrder(root->left);
		cout << root->val << " ";
		inOrder(root->right);
	}
	cout<<endl;
}

3.后序

void postOrder(TreeNode* root)
{
	if (root)
	{
		postOrder(root->left);
		postOrder(root->right);
		cout << root->val << " ";
	}
	cout<<endl;
}

三.非递归

1.前序

(1)建立一个栈,存储节点;
定义当前节点指向根节点;
(2)当当前节点不为空或者栈不为空时:
遍历最左路径,并输出这条路径的节点的值;
拿到栈顶的节点,让当前节点指向栈顶节点的右孩子,栈顶元素出栈;
(3)重复上一步;

void preOrderTranversal(TreeNode* root)
{
	TreeNode* cur = root;
	stack<TreeNode*> st;

	while (cur || !st.empty())
	{
		//遍历最左路径,让这条路径的节点入栈
		//在入栈的同时输出节点的值
		while (cur)
		{
			st.push(cur);
			cout << cur->val << " ";
			cur = cur->left;
		}

		TreeNode* top = st.top();
		st.pop();//栈顶元素出栈

		cur = top->right;//当前节点指向栈顶元素的右孩子
	}
	cout << endl;
}

2.中序

(1)建立一个栈,存储节点;
定义当前节点指向根节点;
(2)当当前节点不为空或者栈不为空时:
遍历最左路径,并让节点入栈;
拿到栈顶元素,此时栈顶元素就是根节点,输出栈顶元素的值;
让当前节点指向栈顶元素的右孩子,栈顶元素出栈;
(3)重复上一步;

void inOrderTranversal(TreeNode* root)
{
	TreeNode* cur = root;
	stack<TreeNode*> st;

	while (cur || !st.empty())
	{
		//遍历最左路径,让这条路径的节点入栈
		while (cur)
		{
			st.push(cur);
			cur = cur->left;
		}

		TreeNode* top = st.top();
		cout << top->val << " ";//输出栈顶元素的值
		st.pop();//让栈顶元素出栈
		
		cur = top->right;//让当前节点指向top的右孩子
	}
	cout << endl;
}

3.后序

(1)建立一个栈,存储节点;
定义当前节点指向根节点;
定义父节点,初始化为空;
(2)当当前节点不为空或者栈不为空时:
遍历最左路径,并让节点入栈;
拿到栈顶元素,此时栈顶元素就是根节点,判断当前节点是否可以访问:
如果当前节点的右子树为空或者右孩子已经访问过了,就输出栈顶元素的值,更新父节点,栈顶元素出栈;
否则访问右子树;
(3)重复上一步;

void postOrderTranversal(TreeNode* root)
{
	TreeNode* cur = root;
	TreeNode* prev = nullptr;//父节点初始为空
	stack<TreeNode*> st;

	while (cur || !st.empty())
	{
		//遍历最左路径,节点入栈
		while (cur)
		{
			st.push(cur);
			cur = cur->left;
		}

		TreeNode* top = st.top();
		//栈顶元素的右孩子等于父节点,或者栈顶元素的右孩子为空,说明当前根节点可以访问
		if (top->right == nullptr || top->right == prev)
		{
			cout << top->val<<" ";
			st.pop();
			prev = top;
		}
		else
		{
			//根节点不能访问,访问根节点的右子树
			cur = top->right;
		}
	}
	cout << endl;
}

非递归前序和后序的不同方式

前序的思想:

  1. 让根节点入栈;
  2. 拿到栈顶元素,将栈顶元素打印,同时让栈顶元素的右孩子和左孩子依次入栈;
  3. 重复上一步,直到栈为空;

后序的思想:

  1. 创建两个栈, 一个辅助栈,一个仓库栈,让根节点先入到辅助栈中;
  2. 让辅助栈的栈顶元素top出栈,同时将top入栈到仓库栈中,如果top有左右孩子,让左右孩子依次入栈到辅助栈;
  3. 重复上一步,直到辅助栈为空;
  4. 将仓库栈的元素出栈并打印;
/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 * };
 */

class Solution {
public:
    /**
     * 
     * @param root TreeNode类 the root of binary tree
     * @return int整型vector<vector<>>
     */
    vector<vector<int> > threeOrders(TreeNode* root) {
        // write code here
        vector<vector<int>> res;
        vector<int> preRes;
        vector<int> inRes;
        vector<int> postRes;
        preOrder(root, preRes);
        inOrder(root, inRes);
        postOrder(root, postRes);
        res.push_back(preRes);
        res.push_back(inRes);
        res.push_back(postRes);
        return res;
    }
private:
    //前序,不同于我之前接触的方法
    void preOrder(TreeNode* root, vector<int>& preRes)
    {
        stack<TreeNode*> st;
        if(root)
        {
            st.push(root);
        }
        while(!st.empty())
        {
            TreeNode* top = st.top();
            st.pop();
            preRes.push_back(top->val);
            if(top->right)
            {
                st.push(top->right);
            }
            if(top->left)
            {
                st.push(top->left);
            }
        }
    }
    //中序,和之前接触的二叉树的遍历方法相同
    void inOrder(TreeNode* root, vector<int>& inRes)
    {
        stack<TreeNode*> st;
        TreeNode* curNode = root;
        while(curNode || !st.empty())
        {
            while(curNode)
            {
                st.push(curNode);
                curNode = curNode->left;
            }
            TreeNode* top = st.top();
            st.pop();
            inRes.push_back(top->val);
            if(top->right)
            {
                curNode = top->right;
            }
        }
    }
    //后序,不同于之前我接触的方法
    void postOrder(TreeNode* root, vector<int>& postRes)
    {
        stack<TreeNode*> tmp;
        stack<TreeNode*> wareHouse;
        if(root)
        {
            tmp.push(root);
        }
        while(!tmp.empty())
        {
            TreeNode* top = tmp.top();
            tmp.pop();
            wareHouse.push(top);
            if(top->left)
            {
                tmp.push(top->left);
            }
            if(top->right)
            {
                tmp.push(top->right);
            }
        }
        while(!wareHouse.empty())
        {
            postRes.push_back(wareHouse.top()->val);
            wareHouse.pop();
        }
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值