leetcode103. 蛇形打印二叉树/锯齿形层次遍历

本文介绍了一种特殊的二叉树遍历方法——蛇形遍历,通过广度优先搜索(BFS)和深度优先搜索(DFS)两种方式实现。在BFS中,使用双端队列来存储节点并控制输出顺序,实现正反向交替输出;在DFS中,通过递归构建双端队列,最后根据层级改变输出方向。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

BFS

层级遍历+蛇形输出

思路:
1、使用广度优先遍历,将二叉树所有节点存放于一个双端队列中。
2、使用分隔符(空节点)将层级分离。
3、使用bool控制每一行的输出顺序即可。
https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal/solution/er-cha-shu-de-ju-chi-xing-ceng-ci-bian-li-by-leetc/
执行用时:8 ms
内存消耗:11.5 MB

/**
 * 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:
    void BFS(deque<TreeNode*>& deq, int& index)
    {
        while (index < deq.size())
        {
            TreeNode* cur = deq[index];
            if (cur == nullptr && index == deq.size()-1)
                return;
            else if(cur == nullptr)
                deq.push_back(nullptr);
            else
            {
                if (cur->left) 
                    deq.push_back(cur->left);
                if (cur->right) 
                    deq.push_back(cur->right);
            }
            index++;
        }
    }
    void toVector(deque<TreeNode*>& deq,vector<vector<int>>& ret)
    {
        if(deq.size() <= 0) return;
        bool forwardPrintf = true;

        int index1 = 0;
        int index2 = 0;
        vector<int> vLayer;
        while (index1 < deq.size()|| index2 < deq.size())
        {
            auto cur =  deq[index2];
            if (cur == nullptr)//翻转打印方向
            {
                if(forwardPrintf)
                    ret.push_back(vLayer);
                else
                {
                    int temp = index2 - 1;
                    while (index1 - 1 < temp)
                    {
                        vLayer.push_back(deq[temp]->val);
                        temp--; 
                    }
                    ret.push_back(vLayer);
                }
                
                vLayer.clear();
                index1 = index2;
                index1++;
                index2++;
                forwardPrintf = !forwardPrintf;
            }
            else if (forwardPrintf)//直接打印
            {
                vLayer.push_back( cur->val);
                index1++;
                index2++;
            }
            else//index2先行
            {
                index2++;
            }
        }
    }
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int>> ret;
        if (root == nullptr) 
            return ret;

        deque<TreeNode*> deq;
        deq.push_back(root);
        deq.push_back(nullptr);

        int index = 0;
        BFS(deq, index);

        
        toVector(deq,ret);
        return ret;
    }
};

BFS遍历时输出

思路:
既然使用双端队列,那就可以直接在队首或者队尾进行增删。
正向打印时,遍历deque中从front开始的所有节点,将其左右子树按序放入队尾push_back;
当正向打印到达deque的第一个nullptr时,保存这之前遍历的元素,改变当前节点至队尾元素,改变遍历方向。
当反向打印时,遍历deque中end()–的元素,将其左右子树反序放入deque的首部push_front;
当反向打印到达deque的第一个nullptr时,保存这之前遍历的元素,pop当前nullptr,使当前节点成为deque的队首元素。

执行用时:4 ms
内存消耗:11.3 MB

/**
 * 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:
    void BfsPro(deque<TreeNode*>& deq,bool bForword,vector<vector<int>>& ret)
    {
        vector<int> layer;
        auto cur = deq.front();
        while (deq.size())
        {
            if (bForword && cur == nullptr)
            {
                ret.push_back(layer);
                layer.clear();

                auto tmp = deq.end();
                tmp--;
                cur = *tmp;
                if (deq.size() == 1 && cur == nullptr)
                    break;

                
                bForword = !bForword;
            }
            else if (!bForword && cur == nullptr)
            {
                ret.push_back(layer);
                layer.clear();

                cur = deq.front();
                if (deq.size() == 1 && cur == nullptr)
                    break;

                bForword = !bForword;
            }
            else if (bForword && cur != nullptr)
            {
                layer.push_back(cur->val);
                if (cur->left) deq.push_back(cur->left);
                if (cur->right) deq.push_back(cur->right);
                deq.pop_front();
                cur = deq.front();
            }
            else if (!bForword && cur != nullptr)
            {
                layer.push_back(cur->val);
                if (cur->right) deq.push_front(cur->right);
                if (cur->left) deq.push_front(cur->left);
                
                deq.pop_back();
                auto tmp = deq.end();
                tmp--;
                cur = *(tmp);
            }
        }
    }
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int>> ret;
        if(root== nullptr)
            return ret;

        deque<TreeNode*> deq;
        deq.push_back(root);
        deq.push_back(nullptr);
        bool bForword = true;

        BfsPro(deq, bForword,ret);
        return ret;
    }
};

DFS

深度优先遍历

如果当前节点的双端队列不存在,则创建一个双端队列,并将该节点加入队列中。
如果当前节点的双端队列已经存在,则直接插入该队列中。
都递归当前节点的左右子节点。

输出时,需要根据层数,改变输出方向。

/**
 * 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:
   void Dfs(TreeNode* root, deque<deque<int>>& deq,int layer)
    {

        if (root == nullptr)
            return;

        if (layer < deq.size())
        {
            deq[layer].push_back(root->val);
        }
        else
        {
            deque<int> tmp;
            tmp.push_back(root->val);
            deq.push_back(tmp);
        }

        Dfs(root->left,deq, layer+1);
        Dfs(root->right, deq,  layer+1);

    }
    void dePrint(deque<deque<int>>& deq,vector<vector<int>>& ret)
    {
        vector<int> layer;
        for (int i = 0; i < deq.size(); ++i)
        {
            if (i % 2 == 0)
            {
                while (deq[i].size())
                {
                    layer.push_back(deq[i][0]);
                    deq[i].pop_front();
                }
            }
            else
            {
                while (deq[i].size())
                {
                    auto tmp = deq[i].end();
                    tmp--;
                    layer.push_back(*(tmp));
                    deq[i].pop_back();
                }
            }
            ret.push_back(layer);
            layer.clear();
        }
    }
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int>> ret;
        if(root== nullptr)
            return ret;

        deque<deque<int>> deq;
        Dfs( root,  deq, 0);
        
        dePrint( deq,ret);
        return ret;
    }
};

由于深度优先遍历时,无法输出结果,所以相比较而言,还是广度优先遍历的方法更优。

锯齿形层次遍历是一种二叉树层次遍历方法,它会按照"之"字形的顺序遍历二叉树的节点。具体实现可以使用队列或者递归的方式来实现。 使用队列的方法可以按照层次遍历的思路来实现,首先将根节点加入队列中,然后依次取出队列中的节点。在每一层遍历时,我们可以使用一个临时列表来存储当前层的节点值,并将下一层的节点按照遍历顺序添加到新的队列中。同时,我们可以使用一个变量来记录当前层的层数,如果层数为偶数,则按照顺序添加到临时列表中;如果层数为奇数,则按照逆序添加到临时列表中。最后将临时列表添加到最终结果中。这样就能实现二叉树锯齿形层次遍历。 另一种实现方式是使用递归来进行遍历。我们可以使用一个辅助函数来实现递归遍历。在遍历过程中,我们可以传递当前节点和当前层的层数作为参数,并根据层数的奇偶性来决定节点值的添加位置。同时,我们可以使用一个列表来存储每一层的节点值,并在递归的最后将列表转换为最终的结果。这样也能实现二叉树锯齿形层次遍历。 综上所述,二叉树锯齿形层次遍历可以使用队列或递归来实现,具体取决于个人的喜好和代码风格。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [二叉树锯齿形层序遍历[分层遍历方式之一 -> 前序遍历+level]](https://blog.csdn.net/qq_43164662/article/details/125512062)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [【LeetCode103. 二叉树锯齿形层次遍历](https://blog.csdn.net/weixin_41888257/article/details/107284460)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值