二叉树的层序遍历问题

leetcode662. 二叉树最大宽度

https://leetcode-cn.com/problems/maximum-width-of-binary-tree/

因为二叉树的结构与满二叉树相同,因此可以用满二叉树的编号方式给二叉树中所有结点编号,当然要通过二叉树的层序遍历来实现。如果一个结点编号为i,那么其左孩子编号就是 2 * i,其右孩子就编号成2 * i + 1。比较重要的是为了防止编号越来越大而超过int的表示范围,可以在给每一层编号的时候减去一个统一的偏移量offset需要在for循环外边定义。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int widthOfBinaryTree(TreeNode* root) {
        if(!root) return 0;
        root->val = 0; // 根节点编号0
        queue<TreeNode *> q;
        q.push(root);
        int ans = 0;

        while(!q.empty()){
            int len = q.size();
            ans = max(ans, q.back()->val - q.front()->val + 1);
            int offset = q.front()->val; // 根节点编号作为所有孩子结点编号的偏移
            for(int i = 0; i < len; ++i){
                TreeNode *node = q.front();
                q.pop();
                node->val -= offset;
                if(node->left){
                    node->left->val = node->val * 2;
                    q.push(node->left);
                } 
                if(node->right){
                    node->right->val = node->val * 2 + 1;
                    q.push(node->right);
                } 
            }
        }

        return ans;

    }
};

此类型题目的基础是二叉树的层序遍历。一般都是用一个辅助队列来实现层序遍历。

https://leetcode-cn.com/problems/binary-tree-level-order-traversal/

while循环中len用来确定下一层有多少个结点。而for循环中每一轮的node都是同一层的结点。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> ans;
        if(!root) return ans;
        vector<int> temp;
        queue<TreeNode *> q;
        q.push(root);

        while(!q.empty()){
            int len = q.size();
            for(int i = 0; i < len; ++i){
                TreeNode *node = q.front();
                q.pop();
                temp.push_back(node->val);
                if(node->left) q.push(node->left);
                if(node->right) q.push(node->right);

            }
            ans.push_back(temp);
            temp.clear();
        }
        return ans;

    }
};

同理N叉树的层序遍历

https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal/submissions/

/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        vector<vector<int>> ans;
        vector<int> temp;
        if(!root) return ans;
        queue<Node *> q;
        q.push(root);

        while(!q.empty()){
            int len = q.size();
            for(int i = 0; i < len; ++i){
                Node *node = q.front();
                q.pop();
                temp.push_back(node->val);
                for(auto &child : node->children){
                    q.push(child);
                }
            }
            ans.push_back(temp);
            temp.clear();
        }
        return ans;
        
    }
};

二叉树的锯齿形层序遍历

https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal/

首先,下边这种解法是错误的。。。

比如这个例子:

我们想要的是第一层 1, 第二层 3,2,第三层4 5,但是下边这种方法第三层的时候先出队的结点时3,所以遍历第三层结点的时候是先遍历的3的孩子,即5在前边,而不是4。

 

 

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int>> ans;
        vector<int> temp;
        if(!root) return ans;
        bool flag = true;
        queue<TreeNode *> q;
        q.push(root);
        while(!q.empty()){
            int len = q.size();
            flag  = !flag;
            for(int i = 0; i < len; ++i){
                TreeNode *node = q.front();
                q.pop();
                temp.push_back(node->val);
                if(flag){
                    if(node->left) q.push(node->left);
                    if(node->right) q.push(node->right);
                }else{
                    if(node->right) q.push(node->right);
                    if(node->left) q.push(node->left);
                }
            }
            ans.push_back(temp);
            temp.clear();
        }
        return ans;

    }
};

还是按原先方法遍历,最后把每一行的遍历结点加入最终结果数组的时候再判断要不要将数组逆序即可。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int>> ans;
        vector<int> temp;
        if(!root) return ans;
        bool flag = false;
        queue<TreeNode *> q;
        q.push(root);
        while(!q.empty()){
            int len = q.size();
            flag  = !flag;
            for(int i = 0; i < len; ++i){
                TreeNode *node = q.front();
                q.pop();
                temp.push_back(node->val);
                if(node->left) q.push(node->left);
                if(node->right) q.push(node->right);
            }
            if(flag) ans.push_back(temp);
            else{
                reverse(temp.begin(), temp.end());
                ans.push_back(temp);
            }
            temp.clear();
        }
        return ans;

    }
};

好的,下面是用C语言实现二叉树层序遍历的代码: ```c #include <stdio.h> #include <stdlib.h> // 定义二叉树节点结构体 typedef struct TreeNode { int val; struct TreeNode* left; struct TreeNode* right; } TreeNode; // 定义队列结构体 typedef struct Queue { struct TreeNode* data[100]; int front; int rear; } Queue; // 初始化队列 Queue* initQueue() { Queue* q = (Queue*)malloc(sizeof(Queue)); q->front = 0; q->rear = 0; return q; } // 入队 void enqueue(Queue* q, TreeNode* node) { q->data[q->rear++] = node; } // 出队 TreeNode* dequeue(Queue* q) { return q->data[q->front++]; } // 判断队列是否为空 int isEmpty(Queue* q) { return q->front == q->rear; } // 二叉树层序遍历 void levelOrder(TreeNode* root) { if (root == NULL) { return; } Queue* q = initQueue(); enqueue(q, root); while (!isEmpty(q)) { int size = q->rear - q->front; for (int i = 0; i < size; i++) { TreeNode* node = dequeue(q); printf("%d ", node->val); if (node->left) { enqueue(q, node->left); } if (node->right) { enqueue(q, node->right); } } printf("\n"); } } int main() { // 构建二叉树 TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode)); root->val = 1; root->left = (TreeNode*)malloc(sizeof(TreeNode)); root->left->val = 2; root->right = (TreeNode*)malloc(sizeof(TreeNode)); root->right->val = 3; root->left->left = (TreeNode*)malloc(sizeof(TreeNode)); root->left->left->val = 4; root->left->right = (TreeNode*)malloc(sizeof(TreeNode)); root->left->right->val = 5; root->right->left = (TreeNode*)malloc(sizeof(TreeNode)); root->right->left->val = 6; root->right->right = (TreeNode*)malloc(sizeof(TreeNode)); root->right->right->val = 7; // 二叉树层序遍历 levelOrder(root); return 0; } ``` 运行结果如下: ``` 1 2 3 4 5 6 7 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值