[数据结构]二叉树遍历的递归非递归实现(前序、中序、后序、层次)

前序

前序遍历按照“根结点-左孩子-右孩子”的顺序进行访问。
给定一个二叉树,返回它的 前序遍历。
示例:

输入: [1,null,2,3]  

       1
        
         2
        /
       3 
       
输出: [1,2,3]

进阶: 递归算法很简单,你可以通过迭代算法完成吗?

递归

vector res需要在方法外声明**

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> res;
    vector<int> preorderTraversal(TreeNode* root) {
	
	if (root != NULL)
	{
		res.push_back(root->val);
		if(root->left!=NULL)
			preorderTraversal(root->left);
		if (root->right != NULL)
			preorderTraversal(root->right);
	}
	return res;
}
};

非递归

思路:
利用堆栈来实现,对于任何一个节点可以看为是根节点,直接访问,随后依次将右孩子和左孩子入栈
循环结束的条件是栈为空

vector<int> preorderTraversal(TreeNode* root) {
    stack<TreeNode*> nodestack;
    vector<int> res;
    if(root==NULL)
        return res;
    else
    {
        nodestack.push(root);
        while(nodestack.empty()==false)
        {
            TreeNode* temp=nodestack.top();
            res.push_back(temp->val);
            nodestack.pop();
            if(temp->right!=NULL)
                nodestack.push(temp->right);
            if(temp->left!=NULL)
                nodestack.push(temp->left);
        }
        return res;
    }
}

中序

中序遍历按照“左孩子-根结点-右孩子”的顺序进行访问。

递归

vector<int> res;
vector<int> inorderTraversal(TreeNode* root) {
    if(root==NULL)
        return res;
    inorderTraversal(root->left);
    res.push_back(root->val);
    inorderTraversal(root->right);
    return res;
}

非递归

思路:
当前节点入栈,随后当前节点为其左孩子节点,循环往复直到没有左孩子。随后访问栈顶元素,并将当前节点设置为其右孩子节点,按照同样的规则对右子树进行访问
遍历结束条件:栈空且当前节点为NULL

vector<int> inorderTraversal(TreeNode* root) {
     stack<TreeNode*> st;
     vector<int> res;
     if(root==NULL)
         return res;
     TreeNode* pn=root;
     while(st.empty()==false||pn!=NULL)
     {
         while(pn!=NULL)
         {
             st.push(pn);  
             pn=pn->left;
         }
         pn=st.top();
         res.push_back(pn->val);
         st.pop();
         if(pn->right!=NULL)
             pn=pn->right;
         else
             pn=NULL;
     }
     return res;
}

后序

后序遍历按照“左孩子-右孩子-根结点”的顺序进行访问。

递归

递归实现
vector<int> res;
vector<int> postorderTraversal(TreeNode* root) {
    if(root==NULL)
        return res;
    else
    {
        postorderTraversal(root->left);
        postorderTraversal(root->right);
        res.push_back(root->val);
    }
    return res;
}

非递归

思路:
增加一个指针pre用以记录上一个访问的节点
对于栈顶的节点如果他没有左右孩子,或者他的左右孩子已经被访问过了则可以直接访问他 (即比较pre和节点左右孩子)
否则依次将他的右孩子、左孩子压栈

vector<int> postorderTraversal(TreeNode* root) {
	stack<TreeNode*> st;
	TreeNode* curr=root;
	TreeNode*  pre=NULL;
	vector<int> res;
	if (root != NULL)
	{
		st.push(root);
		while (!st.empty())
		{
			curr = st.top();
			if ((curr->left == NULL&&curr->right == NULL) ||
				(pre != NULL && (pre == curr->left || pre == curr->right))
				)
			{
				st.pop();
				res.push_back(curr->val);
				pre = curr;
			}
			else
			{
				if (curr->right != NULL)
					st.push(curr->right);
				if (curr->left != NULL)
					st.push(curr->left);
			}
		}
	}
	return res;
}

层次

非递归

思路:
通过队列来实现,每当访问一个节点,节点出栈的同时依次把它的左孩子、右孩子压栈。
循环终止的条件为队列为空
内部循环用以分层次访问,循环开始前记录队列长度,即当前层次的节点数

vector<vector<int>> levelOrder(TreeNode* root) {
	vector<vector<int>> result;
	queue<TreeNode*> nodequeue;
	if (root==NULL)
	{
		return result;
	}
	nodequeue.push(root);
	while (!nodequeue.empty())
	{
		int count = nodequeue.size();
		vector<int> levelresult;
		while (count--)
		{
			TreeNode* temp = nodequeue.front();
			nodequeue.pop();
			levelresult.push_back(temp->val);
			if (temp->left) nodequeue.push(temp->left);
			if (temp->right) nodequeue.push(temp->right);
		}
		result.push_back(levelresult);
	}
	return result;
}
原文地址:https://www.cnblogs.com/wendyy/p/9324110.html