按之字形顺序打印二叉树

思路(双栈法):

我们可以利用两个栈遍历这棵二叉树,第一个栈s1从根节点开始记录第一层,然后依次遍历两个栈,遍历第一个栈时遇到的子节点依次加入第二个栈s2中,即是第二层:而遍历第二个栈s2的时候因为是先进后出,因此就是逆序的,再将第二个栈s2的子节点依次加入第一个栈s1中:于是原本的逆序在第一个栈s1中又变回了正序,如果反复交替直到两个栈都空为止。

具体做法:

step 1:首先判断二叉树是否为空,空树没有打印结果。

step 2:建立两个辅助栈,每次依次访问第一个栈s1与第二个栈s2,根节点先进入s1.

step 3:依据依次访问的次序,s1必定记录的是奇数层,访问节点后,将它的子节点(如果有)依据先左后右的顺序加入s2,这样s2在访问的时候根据栈的先进后出原理就是右节点先访问,正好是偶数层需要的从右到左访问次序。偶数层则正好相反,要将子节点(如果有)依据先右后左的顺序加入s1,这样在s1访问的时候根据栈的先进后出原理就是左节点先访问,正好是奇数层需要的从左到右访问次序。

step 4:每次访问完一层,即一个栈为空,则将一维数组加入二维数组中,并清空以便下一层用来记录。

图示:

链接

代码:

class Solution{
    public:
    //定义一个函数用于之字形打印二叉树
    //传入二叉树的根节点,返回的是二维数组
    vector<vector<int>> Print(TreeNode* pRoot){
        //定义一个二维数组用于存最后的结果
        vector<vector<int>>res;
        TreeNode* head=pRoot;
        //如果二叉树为空,则直接返回res
        if(pRoot==NULL){
            return res;
        }
        //否则就创建两个栈,由于栈是先进后出的结构
        //所以可以先将根节点放入栈1中,再将栈1中的节点进行扩展,将扩展的点(从左节点到右节点的顺序)放入栈2中
        //再将栈2中的点进行扩展,从右子节点到左子节点进行扩展,将扩展的点放入栈1中,这样刚好能实现之字形打印二叉树
        stack<TreeNode*>s1;
        stack<TreeNode*>s2;
        s1.push(head);
        //只要栈1或栈2中有一个栈还有点没有扩展,就继续扩展
        while(!s1.empty()||!s2.empty()){
            //用一个一维数组存每层的节点的编号
            vector<int>now;
            //只要栈1的点还没有扩展完,就将每个点进行扩展,将扩展好的点输出存入now数组中,再将该点的所有子节点(从左子节点到右子节点)扩展添加到栈2中
            while(!s1.empty()){
                TreeNode* t=s1.top();
                now.push_back(t->val);
                if(t->left){
                    s2.push(t->left);
                }
                if(t->right){
                    s2.push(t->right);
                }
                s1.pop();
            }
            //将该层的节点插入最后的二维数组
            if(now.size()){
                res.push_back(now);
            }
            //将数组now清空,就可以继续存下一层的节点
            now.clear();
            //还要栈2不为空,就将栈2的点进行扩展(从右子节点到左子节点),将出栈的点插入数组中
            while(!s2.empty()){
                TreeNode* p=s2.top();
                now.push_back(p->val);
                if(p->right){
                    s1.push(p->right);
                }
                if(p->left){
                    s1.push(p->left);
                }
                s2.pop();
            }
            if(now.size()){
                res.push_back(now);
            }
        }
        return res;
    }

};