一、题目解析
对于递归方法的前序遍历十分简单,但对于一位合格的程序猿而言,需要掌握将递归转化为非递归的能力,毕竟递归调用的时候会调用大量的栈帧,存在栈溢出风险。
二、算法原理
递归调用本质是系统建立栈帧,而非递归则是用栈来存储数据,实现类似递归的效果。
首先,我们先简单了解一下递归调用时,是如何遍历的?
前序遍历,由根、左子树、右子树的顺序遍历,打印时直接打印根节点的值。
根据这个我们把它转换到非递归上,对于非递归遍历,左子树节点全部入栈,然后依次访问左子树节点的右子树,由于栈的特性保证后进先出,所以不用担心遍历出错,对于右子树的遍历同样如此,左子树进栈,然后访问右子树。
由此我们可以看出非递归本质上与递归没有多大差别。
三、代码示例
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root)
{
stack<TreeNode*> st;
TreeNode* cur = root;
vector<int> v;
while(cur || !st.empty())
{
//访问一棵树的开始
//1.访问左路节点,左路节点入栈,后续依次访问左路节点的右子数
while(cur)
{
v.push_back(cur->val);
st.push(cur);
cur = cur->left;
}
//依次访问左路节点的右子树
TreeNode* top = st.top();
st.pop();
//子问题的方式访问右子树
cur = top->right;
}
return v;
}
};
push是栈的入数据操作,top则是栈的获取栈顶元素操作,pop则是栈的删数据操作,push_back是vector的尾插操作
四、非递归遍历流程
看到最后,如果对您有所帮助,还请点赞、收藏和关注,点点关注不迷路,我们下期再见!