Leetcode(144)-二叉树的前序遍历

给定一个二叉树,返回它的 前序 遍历。

 示例:

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

输出: [1,2,3]

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

二叉树的前序遍历有递归和非递归两种做法。

在介绍这两种方法之前,我首先介绍下,二叉树如何建立

struct TreeNode
{
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x):val(x),left(NULL),right(NULL) {}
};
void createBiTree(TreeNode* &T) //&的意思是传进来节点指针的引用,目的是让传递进来的指针发生改变
{
    int c;
    cin >> c;
    if(-1 == c)             //当遇到-1时,令树的根节点为NULL,从而结束该分支的递归
        T = NULL;
    else
    {
        T = new TreeNode(0);
        T->val=c;
        createBiTree(T->left);
        createBiTree(T->right);
    }
}

(1)递归

思路:用递归的方法,这里用vector作为返回值,需要注意的是,当vector很大时,因为这样存在创建临时对象并拷贝的过程,空间时间开销会很大。一般返回的是引用,但是不能返回临时对象的引用。这里在外面定义了vector,因为如果定义在内部,每次递归都会重新创建一个vector,不符合我们想要的结果。

vector<int> a;
vector<int> preorderTraversal(TreeNode* root) 
{
if(root) { a.push_back(root->val);//这里每次将本次循环的根节点值放入数组中 preorderTraversal(root->left); preorderTraversal(root->right); } return a; }

(2)非递归

思路:非递归的形式,也叫作迭代形式。在遍历根节点后还要回来,因此要基于栈(先进后出)来保存节点。

根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。因此其处理过程如下:

     对于任一结点P:

     1)访问结点P,并将结点P入栈;

     2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;

     3)直到P为NULL并且栈为空,则遍历结束。

vector<int> preorderTraversal(TreeNode* root)//非递归实现
{
    stack<TreeNode*> s;
    TreeNode* p=root;
    vector<int> a;
    while(p!=NULL || !s.empty())//这里是||,只要P不为空,或者栈里有节点,就要继续
    {
        while(p)
        {
            s.push(p);
            a.push_back(p->val);
            p=p->left;
        }
        if(!s.empty())
        {
            p=s.top();
            s.pop();
            p=p->right;
        }
    }
    return a;
}

猜你喜欢

转载自www.cnblogs.com/mini-coconut/p/9077370.html