Given a binary tree, return the preorder traversal of its nodes' values.
For example:
Given binary tree {1,#,2,3}
,
1 \ 2 / 3
return [1,2,3]
.
Note: Recursive solution is trivial, could you do it iteratively?
本题为二叉树的先序遍历,也就是先根遍历,但是提示不能用递归,所以就是二叉树先序遍历的非递归实现。现在为了在面试中能够灵活的掌握非递归遍历,三种遍历方法都总结一下,方面以后的面试中复习使用。
先序遍历:
递归:
void traverse(Tree *root)
{
if(root==NULL) return;
visit(root->data);
traverse(Tree->left);
traverse(Tree->right);
}
非递归(用栈实现,是因为递归的过程就是程序自动压栈);
void traverse(Tree *root)
{
stack.push(root);
while(!stack.empty())
{
temp=stack.top();
stack.pop();
visit(temp->data);
stack.push(temp->right);//先将右儿子入栈,因为比左儿子更晚访问到
stack.push(temp->left);
}
}
中序遍历:
递归:
void traverse(Tree *root){
if(root==NULL) return;
traverse(Tree->left);
visit(root->data);
traverse(Tree->right);
}
后序遍历:
递归:
void traverse(Tree *root){
if(root==NULL) return;
traverse(Tree->left);
traverse(Tree->right);
visit(root->data);
}
非递归1:
后序遍历的非递归实现是三种遍历方式中最难的一种。因为在后序遍历中,要保证左孩子和右孩子都已被访问并且左孩子在右孩子前访问才能访问根结点,这就为流程的控制带来了难题。下面介绍两种思路。
第一种思路:对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问,因此其右孩子还为被访问。所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是否是第一次出现在栈顶。
代码实现:
/**
* 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> preorderTraversal(TreeNode* root) {
TreeNode* temp;
stack<TreeNode *> st;
st.push(root);
while(!st.empty())
{
temp=st.top();
st.pop();
visit(temp->val);
st.push(temp->right);
st.push(temp->left);
}
}
};