今天在刷leetcode时,挑了二叉树的第一题来做。题目很简单,就是中序遍历二叉树,不过要求是得用循环的方式实现。
二叉树最初是在本科学习数据结构时接触到的,现在已经基本忘光了。因此我翻了一下书,发现中序遍历的基本要求是:遍历左子树,根节点,右子树。初学者可能会混淆的一点,是将左子树和右子树当做左节点和右节点。换言之,遍历左子树,需要从左子树的根节点出发,再进行左子树->根节点->右子树的遍历过程。前序遍历和后序遍历的过程亦如是。
言归正传。通常是通过递归调用的方法完成二叉树遍历,简单清晰。题目给出的要求,目的在于开拓新的思路。solution中给出了两种解法。
方法一的基本思路和递归法基本是一致的。它先逐次向左遍历,直到为空,并用一个堆栈存储遍历的值,将最后一个节点的值插入保存结果的数组中,并将其推出。在最后一个节点处,可能有右子树存在,因此还需要再对其进行向左遍历。结束后,堆栈自底向上存储着根节点的值。依次将其推出,并重复以上过程可得到中序遍历的结果。在https://leetcode.com/problems/binary-tree-inorder-traversal/solution/ 中有详细的动画演示和说明,此处不再赘述。我试着用这种方式完成二叉树的后序遍历,代码如下:
class Solution {
public:
vector<int> inorderTraversal(TreeNode *root) {
vector<int> res;
TreeNode *p=root,*pre=NULL; //pre记录前一遍历节点
stack<TreeNode> temp;
temp.push(*p); //根节点入栈
while(!temp.empty())
{
p=&(temp.top());
if((p->left==NULL&&p->right==NULL)||(pre!=NULL&&(pre==p->left||pre==p->right)))
{
res.push_back(p->val);
temp.pop(); //出栈
pre=p;
}
else //将右节点、左节点依次入栈
{
if(p->right!=NULL)
temp.push(*p->right);
if(p->left!=NULL)
temp.push(*p->left);
}
}
return res;
}
};
方法二称为Morris遍历,它的做法比较独特,同样在上面的链接中有说明。具体不再阐述。