一、前序非递归遍历
1、算法思路
利用栈先进后出的特性,在一个有三个结点的子树中,先对根节点做出操作,再将右子树结点入栈,再将左子树结点入栈,这样利用栈遍历的顺序就是根----左-----右(因为根已经最先处理)。
思路比较简单,直接看源码即可理解。
2、源码
void Pre_Travel(TreeNode* root)
{
stack<TreeNode*> stackTree;
if (root == NULL) return;
stackTree.push(root);
while (stackTree.size() > 0)
{
TreeNode* tempNode = stackTree.top();
stackTree.pop();
printf("%d ", tempNode->val);
if (tempNode->right != NULL)
stackTree.push(tempNode->right);
if (tempNode->left != NULL)
stackTree.push(tempNode->left);
}
}
二、中序遍历
1、算法思路
最重要的第一步就是,先找到左子树中最后一个没有左子节点的结点。
剩下内容比较简单 ,容易理解,看源码即可。
2、源码
void Mid_Travel(TreeNode* root)
{
if (root == NULL)
return;
stack<TreeNode*> stackTree;
TreeNode* p = root;
while (p || stackTree.size() > 0)
{
//到最后一个没有左子树的结点
while (p)
{
stackTree.push(p);
p = p->left;
}
if (stackTree.size() > 0)
{
TreeNode* tempNode = stackTree.top();
stackTree.pop();
printf("%d ", tempNode->val);
//对右子树继续进行遍历其左子树
p = tempNode->right;
}
}
}
三、后序遍历
1、算法思路
三种非递归算法中,后序遍历算是相对更加复杂一点,复杂的原因在于,对于根节点的访问只有在子节点都被访问之后才能进行,这就需要使用一个缓存,来记录上次访问的结点,再将当前访问结点的左右子树和缓存比较,如果相等,说明其左右子树已经被访问过,此时可以读取当前节点,反之不行。
2、源码
void Pos_Travel(TreeNode* root)
{
if (root == NULL)
return;
stack<TreeNode*> stackTree;
TreeNode* pre = NULL;
stackTree.push(root);
while (stackTree.size() > 0)
{
TreeNode* tempNode = stackTree.top();
//如果左右子树被访问过
if ((tempNode->left == NULL && tempNode->right == NULL) || ((pre != NULL) && (pre == tempNode->left || pre == tempNode->right)))
{
printf("%d ", tempNode->val);
pre = tempNode;
stackTree.pop();
}
//左右子树没有被访问过
else
{
if (tempNode->right != NULL)
stackTree.push(tempNode->right);
if (tempNode->left != NULL)
stackTree.push(tempNode->left);
}
}
}
四、完整Demo
#include <vector>
#include <stack>
using namespace std;
struct TreeNode
{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int v) :val(v), left(NULL), right(NULL) {};
};
class Solution
{
public:
void Pre_Travel(TreeNode* root)
{
stack<TreeNode*> stackTree;
if (root == NULL) return;
stackTree.push(root);
while (stackTree.size() > 0)
{
TreeNode* tempNode = stackTree.top();
stackTree.pop();
printf("%d ", tempNode->val);
if (tempNode->right != NULL)
stackTree.push(tempNode->right);
if (tempNode->left != NULL)
stackTree.push(tempNode->left);
}
}
void Mid_Travel(TreeNode* root)
{
if (root == NULL)
return;
stack<TreeNode*> stackTree;
TreeNode* p = root;
while (p || stackTree.size() > 0)
{
//到最后一个没有左子树的结点
while (p)
{
stackTree.push(p);
p = p->left;
}
if (stackTree.size() > 0)
{
TreeNode* tempNode = stackTree.top();
stackTree.pop();
printf("%d ", tempNode->val);
//对右子树继续进行遍历其左子树
p = tempNode->right;
}
}
}
void Pos_Travel(TreeNode* root)
{
if (root == NULL)
return;
stack<TreeNode*> stackTree;
TreeNode* pre = NULL;
stackTree.push(root);
while (stackTree.size() > 0)
{
TreeNode* tempNode = stackTree.top();
//如果左右子树被访问过
if ((tempNode->left == NULL && tempNode->right == NULL) || ((pre != NULL) && (pre == tempNode->left || pre == tempNode->right)))
{
printf("%d ", tempNode->val);
pre = tempNode;
stackTree.pop();
}
//左右子树没有被访问过
else
{
if (tempNode->right != NULL)
stackTree.push(tempNode->right);
if (tempNode->left != NULL)
stackTree.push(tempNode->left);
}
}
}
};
void main()
{
TreeNode* root=new TreeNode(3);
root->left = new TreeNode(2);
root->right = new TreeNode(5);
root->left->left = new TreeNode(4);
root->left->right = new TreeNode(7);
Solution solution;
solution.Mid_Travel(root);
}