算法 二叉树2 || 层序遍历 226.翻转二叉树 101. 对称二叉树 104.二叉树的最大深度 111 二叉树的最小深度 222.完全二叉树的节点个数

news2024/10/6 10:35:37

102 二叉树的层序遍历

队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。
而这种层序遍历方式就是图论中的广度优先遍历,只不过我们应用在二叉树上。
在这里插入图片描述

迭代法:

/**
 * 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>> res;
        queue<TreeNode*> que;
        if(root == nullptr) return {};
        que.push(root);
        while(!que.empty()){
            int size = que.size();
            vector<int> vec;
            for(int i = 0; i < size; ++i){
                TreeNode* cur = que.front();
                que.pop();
                vec.push_back(cur->val);
                if(cur->left)  que.push(cur->left);
                if(cur->right) que.push(cur->right);
            }
            res.push_back(vec);
        }
        return res;
    }
};

递归法:
递归在遍历的时候,会一层层下去,不能像队列一样遍历一层处理一层。所以递归法层序遍历可以使用变量depth来协助指明当前元素的深度。因为存放元素的容器是二维数组,横向的顺序可以根据左右元素的处理顺序决定,纵向则可以使用depth来控制
其中注意这一行:
if (result.size() == depth) result.push_back(vector());
递归一路向左遍历,遇到每一行的最左边的第一个值才重新创建一行。
在这里插入图片描述

class Solution {
public:
    void order(TreeNode* cur, vector<vector<int>>& result, int depth)
    {
        if (cur == nullptr) return;
        if (result.size() == depth) result.push_back(vector<int>());
        result[depth].push_back(cur->val);
        order(cur->left, result, depth + 1);
        order(cur->right, result, depth + 1);
    }
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> result;
        int depth = 0;
        order(root, result, depth);
        return result;
    }
};

107.二叉树的层次遍历 II

很简单,把102的res 反转一下就行

class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        vector<vector<int>> result;
        while (!que.empty()) {
            int size = que.size();
            vector<int> vec;
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                vec.push_back(node->val);
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            result.push_back(vec);
        }
        reverse(result.begin(), result.end()); // 在这里反转一下数组即可
        return result;

    }
};

199.二叉树的右视图

注意题意:是右视图,而不是只看最右侧的节点。所以下面这个二叉树返回的应该是1 3 4而不是 1 3。在遍历的时候依旧要遍历左子树,只是返回每一层最右侧的值即可。
在这里插入图片描述

/**
 * 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<int> rightSideView(TreeNode* root) {
        if(root == nullptr) return {};
        vector<int> res;
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty()){
            int size = que.size();
            for(int i = 0; i<size; i++){
                TreeNode* cur = que.front();
                que.pop();
                if(i == size-1) res.push_back(cur->val);
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
            } 
        }
        return res;
    }
};

637.二叉树的层平均值

class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        vector<double> result;
        while (!que.empty()) {
            int size = que.size();
            double sum = 0; // 统计每一层的和
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                sum += node->val;
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            result.push_back(sum / size); // 将每一层均值放进结果集
        }
        return result;
    }
};


429.N叉树的层序遍历

别被什么用null分割给唬住,看node 的结构,以前是两根左右指针,现在是一个vector<Node*>容器而已

class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        queue<Node*> que;
        if (root != NULL) que.push(root);
        vector<vector<int>> result;
        while (!que.empty()) {
            int size = que.size();
            vector<int> vec;
            for (int i = 0; i < size; i++) {
                Node* node = que.front();
                que.pop();
                vec.push_back(node->val);
                for (int i = 0; i < node->children.size(); i++) { // 将节点孩子加入队列
                    if (node->children[i]) que.push(node->children[i]);
                }
            }
            result.push_back(vec);
        }
        return result;

    }
};

515.在每个树行中找最大值

class Solution {
public:
    vector<int> largestValues(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        vector<int> result;
        while (!que.empty()) {
            int size = que.size();
            int maxValue = INT_MIN; // 取每一层的最大值
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                maxValue = node->val > maxValue ? node->val : maxValue;
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            result.push_back(maxValue); // 把最大值放进数组
        }
        return result;
    }
};

116.填充每个节点的下一个右侧节点指针

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;
    Node* next;

    Node() : val(0), left(NULL), right(NULL), next(NULL) {}

    Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}

    Node(int _val, Node* _left, Node* _right, Node* _next)
        : val(_val), left(_left), right(_right), next(_next) {}
};
*/

class Solution {
public:
    Node* connect(Node* root) {
        if (root == nullptr) return root;
        queue<Node*> que;
        if(root->left) que.push(root->left);
        if(root->right) que.push(root->right);
        while(!que.empty()){
            int size = que.size();
            for(int i = 1; i < size; ++i){
                Node* cur1 = que.front(); //左
                que.pop();
                Node* cur2 = que.front(); //右
                cur1->next = cur2;
                if(cur1->left) que.push(cur1->left);
                if(cur1->right) que.push(cur1->right);
                if(i == size-1){
                    que.pop();
                    if(cur2->left) que.push(cur2->left);
                    if(cur2->right) que.push(cur2->right);
                } 
                
            }
        }
        return root;
    }
};

117.填充每个节点的下一个右侧节点指针II

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;
    Node* next;

    Node() : val(0), left(NULL), right(NULL), next(NULL) {}

    Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}

    Node(int _val, Node* _left, Node* _right, Node* _next)
        : val(_val), left(_left), right(_right), next(_next) {}
};
*/

class Solution {
public:
    Node* connect(Node* root) {
        if(root == NULL) return root;
        queue<Node*> que;
        que.push(root);
        while(!que.empty()){
            int size = que.size();
            Node* pre;
            Node* cur;
            for(int i = 0; i < size; ++i){
                if(i == 0){
                    pre = que.front();
                    que.pop();
                    cur = pre;
                }else{
                    cur = que.front();
                    que.pop();
                    pre->next = cur;
                    pre = cur;
                }
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
            }
        }
        return root;
    }
};

104.二叉树的最大深度

/**
 * 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 maxDepth(TreeNode* root) {
        if(root == nullptr) return 0;
        int depth = 0;
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty()){
            int size = que.size();
            for(int i = 0; i < size; ++i){
                TreeNode* cur = que.front();
                que.pop();
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
            }
            depth++;
        }
        return depth;
    }
};

111.二叉树的最小深度

/**
 * 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 minDepth(TreeNode* root) {
        if(root == nullptr) return 0;
        int depth = 0;
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty()){
            int size = que.size();
            depth++;
            for(int i = 0; i < size; ++i){
                TreeNode* cur = que.front();
                que.pop();
                if(cur->left == nullptr && cur->right == nullptr) return depth;
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);

            }
        }
        return depth;
    }
};

226.翻转二叉树

递归的时候除了中序都可以(中序会让部分节点反转两次)
递归法:

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == NULL) return root;
        swap(root->left, root->right);  // 中
        invertTree(root->left);         // 左
        invertTree(root->right);        // 右
        return root;
    }
};

深度迭代法(stack)

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == NULL) return root;
        stack<TreeNode*> st;
        st.push(root);
        while(!st.empty()) {
            TreeNode* node = st.top();              // 中
            st.pop();
            swap(node->left, node->right);
            if(node->right) st.push(node->right);   // 右
            if(node->left) st.push(node->left);     // 左
        }
        return root;
    }
};

101. 对称二叉树

思路:
1、递归
本题遍历只能是“后序遍历”,因为我们要通过递归函数的返回值来判断两个子树的内侧节点和外侧节点是否相等。
正是因为要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树的遍历顺序是右左中。
在终止条件中,首先看两个中节点是不是相同,如果中节点都不相同就没必要往下看,然后才是他们对应子树,只有子树相同,中节点这里才能返回true。

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if (root == NULL) return true;
        return compare(root->left,root->right);
    }
    bool compare(TreeNode* left, TreeNode* right){
        if(left == nullptr && right != nullptr) return false;
        else if(left != nullptr && right == nullptr) return false;
        else if(left == nullptr && right == nullptr) return true;
        else if(left->val != right->val) return false;

        bool isleft = compare(left->left,right->right);
        bool isright = compare(left->right, right->left);
        return isleft && isright;
    }
};

2、层序遍历,放进队列中,两两取出比较即可

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(root == nullptr) return true;
        queue<TreeNode*> que;
        que.push(root->left);
        que.push(root->right);
        while(!que.empty()){
            TreeNode* left = que.front(); que.pop();
            TreeNode* right = que.front(); que.pop();
            if(left == nullptr && right != nullptr) return false;
            else if(left != nullptr && right == nullptr) return false;
            else if(left == nullptr && right == nullptr) continue;
            else if(left->val != right->val) return false;

            que.push(left->left); que.push(right->right);
            que.push(left->right); que.push(right->left);
        }
        return true;
    }
};

3、深度遍历,使用栈
把队列直接换成栈就可以

104.二叉树的最大深度

在层序遍历中,使用的队列。现在使用递归法
本题可以使用前序(中左右),也可以使用后序遍历(左右中),使用前序求的就是深度,使用后序求的是高度。

二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数或者节点数(取决于深度从0开始还是从1开始)
二叉树节点的高度: 指从该节点到叶子节点的最长简单路径边的条数后者节点数(取决于高度从0开始还是从1开始)

1、而根节点的高度就是二叉树的最大深度,所以本题中我们通过后序求的根节点高度来求的二叉树最大深度

class Solution {
public:
    int maxDepth(TreeNode* root) {
        return maxdepth(root);
    }
    int maxdepth(TreeNode* cur){
        if(cur == nullptr) return 0;
        int depth ;
        int leftdepth = maxdepth(cur->left);
        int rightdepth = maxdepth(cur->right);
        depth = max(leftdepth,rightdepth);
        return depth+1; //depth记录的是当前中节点左右两节点的高度。返回的时候要加上中节点自身的高度,所以返回depth+1
    }
};

2、真正求深度的逻辑 前序遍历

class Solution {
public:
    int result;
    int maxDepth(TreeNode* root) {
        if(root == nullptr) return 0;
        result = 0;
        maxdepth(root,1);
        return result;
    }
    void maxdepth(TreeNode* cur,int depth){
        result = depth > result ? depth : result;
        if(cur->left == nullptr && cur->right == nullptr) return;
        
        if(cur->left){
            depth++;
            maxdepth(cur->left,depth);
            depth--;
        }
        if(cur->right){
            depth++;
            maxdepth(cur->right,depth);
            depth--;
        }
    }
};

111 二叉树的最小深度

前序遍历:

class Solution {
private:
    int result;
    void getdepth(TreeNode* node, int depth) {
        if (node->left == NULL && node->right == NULL) {
            result = min(depth, result);  
            return;
        }
        // 中 只不过中没有处理的逻辑
        if (node->left) { // 左
            getdepth(node->left, depth + 1);
        }
        if (node->right) { // 右
            getdepth(node->right, depth + 1);
        }
        return ;
    }

public:
    int minDepth(TreeNode* root) {
        if (root == NULL) return 0;
        result = INT_MAX;
        getdepth(root, 1);
        return result;
    }
};

后序遍历(很不熟)

class Solution {
public:
    int getDepth(TreeNode* node) {
        if (node == NULL) return 0;
        int leftDepth = getDepth(node->left);           // 左
        int rightDepth = getDepth(node->right);         // 右
                                                        // 中
        // 当一个左子树为空,右不为空,这时并不是最低点
        if (node->left == NULL && node->right != NULL) { 
            return 1 + rightDepth;
        }   
        // 当一个右子树为空,左不为空,这时并不是最低点
        if (node->left != NULL && node->right == NULL) { 
            return 1 + leftDepth;
        }
        int result = 1 + min(leftDepth, rightDepth);
        return result;
    }

    int minDepth(TreeNode* root) {
        return getDepth(root);
    }
};

222.完全二叉树的节点个数

class Solution {
public:
    int countNodes(TreeNode* root) {
        int leftcount = 0;
        int rightcount = 0;

        if(root == nullptr) return 0;
        TreeNode* left = root->left;
        TreeNode* right = root->right;
        while(left){
            leftcount++;
            left = left->left;
        }
        while(right){
            rightcount++;
            right = right->right;
        }
        if(leftcount == rightcount){
            return (2<<leftcount) - 1;
        }

        return countNodes(root->left) + countNodes(root->right) + 1;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/425988.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot和vue写个小项目

遵循“约定优于配置”的原则&#xff0c;只需要很少的配置或使用默认的配置。 能够使用内嵌的Tomcat、Jetty服务器&#xff0c;不需要部署war文件。 提供定制化的启动器Starters,简化Maveni配置&#xff0c;开箱即用。 纯&#xff09;java配置&#xff0c;没有代码生成&#xf…

4月11日,每天30秒,昨夜今晨一览无余/我国首条“西氢东送”管道纳入国家规划/国际机构:中国经济蓬勃复苏,展现广阔投资

-> 昨天的世界(点击进入) <- http://mp.weixin.qq.com/s?__bizMzU4MzQ4Mzk0Nw&mid2247488724&idx1&snd19817d3c7fd9aeb521052090eb439e0&chksmfda90390cade8a864965c805b86acd253f5d74368ae8767b7f00b80d4af5bcc42feef7635641&scene21#wechat_redir…

Qt扫盲-Qt图表类综述

Qt支持图表类综述一、概述二、图表类型1. 折线图和柱状图2. 面积图和散点图3. 柱状图4. 饼图5. 盒须图6. 烛台图表7. 星座图图表三、坐标轴 Axes四、图例五、与图表交互1. 动态绘制数据2. 深入数据3. 缩放和滚动4. 鼠标悬停六、主题一、概述 Qt Charts支持创建时尚的、交互式的…

Jetpack Compose之对话框和进度条

概述 对话框和进度条其实并无多大联系&#xff0c;放在一起写是因为两者的内容都不多&#xff0c;所以凑到一起&#xff0c;对话框是我们平时开发使用得比较多的组件&#xff0c;像隐私授权&#xff0c;用户点击删除时给用户提示这是一个危险操作等&#xff0c;进度条的使用频…

一文吃透Elasticsearch

本文已经收录到Github仓库&#xff0c;该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点&#xff0c;欢迎star~ Github地址 如果访问不了Github&#xff0c…

【自制】我造了一台 钢 铁 侠 的 机 械 臂 !【硬核】

有人说:一个人从1岁活到80岁很平凡,但如果从80岁倒着活,那么一半以上的人都可能不凡。 生活没有捷径,我们踩过的坑都成为了生活的经验,这些经验越早知道,你要走的弯路就会越少。

当我跑步时在想什么

最近好几个人对我说&#xff1a;你瘦了。这是非常激励人心的反馈&#xff0c;验证了跑步是有效的。只要今天开始锻炼&#xff0c;最胖的时候就算过去了&#xff0c;余生都会越来越美。前几天佛山50km徒步&#xff0c;带小朋友走了一半。下午有运动会&#xff0c;就没有走完了。…

提高职场效率,原来可以这么简单

身为职场人&#xff0c;你是否也有过类似的经历 看上去忙的很&#xff0c;手头东西又杂又多&#xff0c;但是一天过去了&#xff0c;到点下班发现啥都没做好当领导布置任务时&#xff0c;常常做了A后就忘记B&#xff0c;任务零碎不会安排做一件事情总是容易拖延&#xff0c;导致…

ROS开发之如何使用RPLidar A1二维激光雷达?

文章目录0.引言1.创建工作空间2.获取rplidar_ros包并编译3.检查雷达端口4.启动launch显示雷达扫描结果0.引言 笔者研究课题涉及多传感器融合&#xff0c;除了前期对ROS工具的学习&#xff0c;还需要用雷达获取数据&#xff0c;进行点云处理。虽然激光雷达已经应用很广泛&#x…

快速构建目标检测coco格式数据集

目标检测coco格式数据集coco数据集快速构建总结coco数据集 首先搞清楚coco格式数据集的组成。在data数据下、分为train、val以及annotations三个文件夹。&#xff08;image是我未划分训练集和测试集的图像存储文件夹&#xff09; 1.train文件夹&#xff1a;用来存放作为训练的图…

一个PostgreSql cli的工具

GitHub - xuejiazhi/pgii: pgii is a PostgreSql cli tool. PostgreSql is developed in CMD or Golang and can be compiled for multiple platforms pgii 是一个PostgreSql cli的工具,对PostgreSql 在CMD或者,采用Golang进行开发,可以多平台下面编译使用&#xff1a; 跨平台…

C/C++|物联网开发入门+项目实战|嵌入式C语言高级|C语言常用关键字及运算符操作-学习笔记(8)

文章目录2-2: C语言常用关键字及运算符操作关键字参考&#xff1a; 麦子学院-嵌入式C语言高级2-2: C语言常用关键字及运算符操作 [重点] 掌握C语言的常用关键宇及其应用场景&#xff0c;使用技巧 关键字 编译器&#xff1a;预先定义了一定意义的字符串&#xff0c;32个。 s…

RHCE3

综合练习&#xff1a;请给openlab搭建web网站 ​ 网站需求&#xff1a; ​ 1.基于域名[www.openlab.com](http://www.openlab.com)可以访问网站内容为 welcome to openlab!!! ​ 2.给该公司创建三个子界面分别显示学生信息&#xff0c;教学资料和缴费网站&#xff0c;基于[www.…

对Spring循环依赖的一些理解

什么是循环依赖 类A有个字段需要注入类B&#xff0c;类B有个字段需要注入类C&#xff0c;类C有个字段需要注入类A&#xff0c;它们之间的依赖关系形成了一个循环。 Spring初始化完一个对象之后会把实例放入单例池&#xff08;singletonObjects&#xff09;中&#xff0c;也就是…

【FFT】快速傅里叶变换

开个新坑&#xff0c; 快速傅里叶变换在现在世界的各个领域都发挥重要作用。 包括音视频压缩、5G、WIFI、卷积、航空、雷达、核武等等 为什么使用快速傅里叶变换 快速傅里叶变换计算复杂度仅为O(nlogn) 而原傅里叶变换是O(n^2) 什么是快速傅里叶变换 是指对傅里叶变换中的重…

蓝桥杯嵌入式第十一届客观题解析

文章目录 前言一、题目1二、题目2三、题目3四、题目4五、题目5六、题目6七、题目7八、题目8九、题目9十、题目10总结前言 本篇文章将为大家带来蓝桥杯嵌入式省赛第11届客观题的解析。 一、题目1 积分电路的作用是对输入信号进行积分,因此在输入一个矩形波时,输出波形将是输…

租车管理系统【GUI/Swing+MySQL】(Java课设)

系统类型 Swing窗口类型Mysql数据库存储数据 使用范围 适合作为Java课设&#xff01;&#xff01;&#xff01; 部署环境 jdk1.8Mysql8.0Idea或eclipsejdbc 运行效果 本系统源码地址&#xff1a;https://download.csdn.net/download/qq_50954361/87682508 更多系统资源库…

【MySQL】索引优化与查询优化(重点:索引失效的11种情况)

【大家好&#xff0c;我是爱干饭的猿&#xff0c;本文重点介绍MySQL的内连接、外连接、索引失效的11种情况、关联查询优化、子查询优化、排序优化、GROUP BY优化、优化分页查询、覆盖索引、索引条件下推和其它查询优化策略的一些问题。 后续会继续分享MySQL和其他重要知识点总…

Springboot基础学习之(二十一):Swagger基础学习(swagger信息介绍,配置扫描接口和开关,分组和接口注释)

什么是Swagger&#xff1f; Swagger2是一个规范和完整的框架&#xff0c;用于生成、描述、调用和可视化RESTful 风格的Web 服务 使用Swagger你只需要按照它的规范去定义接口及接口相关的信息。再通过Swagger衍生出来的一系列项目和工具&#xff0c;就可以做到生成各种格式的接口…

Flutter 滚动组件ListView,GridView,Sliver以及滚动监听

前言 身是菩提树 心是明镜台 时时勤拂拭 模式染尘埃 这玩意不难&#xff0c;就是东西多。。。 1 看一下继承关系 class GridView extends BoxScrollView abstract class BoxScrollView extends ScrollView abstract class ScrollView extends StatelessWidget 2 下面是scr…