【每日一题】【(双端)队列初始化&工具类&层次遍历】2022年1月29日-NC14 按之字形顺序打印二叉树...

介绍三种实现二叉树之字形层序遍历的方法:利用队列结合翻转操作、通过ArrayList的重载add函数实现不同方向的插入、采用双端队列进行高效出队与入队。

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

描述
给定一个二叉树,返回该二叉树的之字形层序遍历,(第一层从左向右,下一层从右向左,一直这样交替)

 

 注意:树的初始化

public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;
    }

类似:链表的初始化

public class LinkNode {
    int val;
    LinkNode next = null;  
    public LinkNode(int val) {
         this.val = val;
    }
}

方法1:普通队列进行层次遍历,隔层使用一次工具类进行翻转

import java.util.*;
/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;
    }

}
*/
public class Solution {
    /**
        使用队列实现层次遍历(先进先出)
        层次遍历判断每一层元素个数不用递归,可以直接看queue的size
    **/
    public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();
        if(pRoot == null) {
            return res;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(pRoot);
        int index = 0;
        while(!queue.isEmpty()) {
            int size = queue.size();
            ArrayList<Integer> arr = new ArrayList<>();
            for(int i = 0; i < size; i++) {
                TreeNode node = queue.poll();
                arr.add(node.val);
                if(node.left != null) {
                    queue.offer(node.left);
                }
                if(node.right != null) {
                    queue.offer(node.right);
                }
            }
            if(index % 2 != 0) {
                Collections.reverse(arr);
            }
            index++;
            res.add(arr);
        }
        return res;
    }
}

注意:队列的初始化是new LinkedList<>();

方法2:使用ArrayList的重载add函数,往前面插入和往后面插入

import java.util.*;

/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;
    }

}
*/
public class Solution {
    /**
        使用队列实现层次遍历(先进先出)
        层次遍历判断每一层元素个数不用递归,可以直接看queue的size
        左右可以使用双端队列实现
    **/
    public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();
        if(pRoot == null) {
            return res;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(pRoot);
        int index = 0;
        while(!queue.isEmpty()) {
            int size = queue.size();
            ArrayList<Integer> arr = new ArrayList<>();
            for(int i = 0; i < size; i++) {
                TreeNode node = queue.poll();
                if(index % 2 == 0) {
                    arr.add(node.val);
                } else {
                    arr.add(0, node.val);
                }
                if(node.left != null) {
                    queue.offer(node.left);
                }
                if(node.right != null) {
                    queue.offer(node.right);
                }
            }
            index++;
            res.add(arr);
        }
        return res;
    }
}

方法3:使用双端队列,每次从不同的方向出队&入队

import java.util.*;

/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    /**
        使用双端队列实现
    **/
    public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer> > res = new ArrayList<>();
        if(pRoot == null) {
            return res;
        }
        Deque<TreeNode> queue = new LinkedList<>();
        queue.offer(pRoot);
        int index = 0;
        while(!queue.isEmpty()) {
            int size = queue.size();
            ArrayList<Integer> arr = new ArrayList<>();
            TreeNode node;
            for(int i = 0; i < size; i++) {
                if(index % 2 == 0) {
                    node = queue.pollFirst();
                    arr.add(node.val);
                if(node.left != null) {
                    queue.offerLast(node.left);
                } 
                if(node.right != null) {
                    queue.offerLast(node.right);
                }
              } else {
                node = queue.pollLast();
                arr.add(node.val);
                if(node.right != null) {
                   queue.offerFirst(node.right);
                }
                 if(node.left != null) {
                   queue.offerFirst(node.left);
                  } 
                }
            }
            index++;
            res.add(arr);
        }
        return res;
    }

}
这是我之前做过的一个项目,把这个设计结构有用的也加入到之前的项目中,做一个最全的:后端项目结构深度解析:testrealend 项目 一、项目根目录核心文件 plaintext testrealend/ ├── app.py # Flask应用主入口 │ api # 职责:创建应用实例、配置扩展、注册API路由 ├── requirements.txt # 依赖包清单(pip install -r 安装) ├── add_user_script.py # 管理员账户初始化脚本 ├── update_user_script.py # 用户信息更新脚本 ├── temp_qrcode.png # 临时二维码图片(水印功能相关) ├── embed/ # 水印嵌入后ZIP文件存储目录 │ # 文件名格式:员工ID_时间戳_嵌入结果.zip ├── compare/ # 水印比对文件目录(原始/提取水印对比) ├── static/ # 静态资源目录(CSS/JS/图片,当前项目未直接使用) └── templates/ # HTML模板目录(后端渲染页面时使用,当前项目为空) 二、核心功能模块解析 (1)API 接口层:resource/ plaintext src/resource/ ├── common_resource.py # 通用接口:注册(Register)、登录(Login)、登出(Logout) ├── adm_resource.py # 管理员接口:员工管理、水印操作 ├── emp_resource.py # 员工接口:数据申请、下载、查看 ├── shp_data_resource.py # SHP数据接口:列表查询、ID检索(重点修改模块) ├── application_resource.py # 数据申请接口:提交/审批流程 ├── nav_resource.py # 导航菜单接口:权限动态渲染 ├── generate_watermark.py # 水印生成接口:二维码/文本转水印 ├── embed_watermark.py # 水印嵌入接口:SHP文件处理 ├── download_file_resource.py # 文件下载接口:权限控制 ├── receive_zip_to_extract.py # ZIP上传接口:解压与验证 └── __init__.py # 包初始化文件 核心逻辑: &bull; 每个.py文件对应一类业务场景,通过Flask-RESTful的Resource类定义 HTTP 接口(GET/POST/PUT/DELETE) &bull; 接口路径通过api.add_resource(ResourceClass, &#39;/api/path&#39;)在app.py中注册 (2)业务逻辑层:server/ plaintext src/server/ ├── shp_data_server.py # SHP数据业务逻辑:数据库查询、文件处理 ├── adm_server.py # 管理员业务逻辑:账户管理、权限校验 ├── emp_server.py # 员工业务逻辑:数据权限控制 ├── common_server.py # 通用业务逻辑:用户认证、 token管理 ├── application_server.py # 数据申请业务逻辑:流程状态管理(注意:拼写应为application) └── __init__.py # 包初始化文件 设计模式: &bull; 资源类(Resource)接收请求后,调用对应服务类(Server)的方法执行具体逻辑 &bull; 实现接口层与业务层解耦,便于单元测试和逻辑复用 (3)数据模型层:model/ plaintext src/model/ ├── Shp_Data.py # SHP文件模型:存储文件元信息(路径/属性/状态) ├── Adm_Account.py # 管理员账户模型:用户名/密码哈希/权限等级 ├── Employee_Info.py # 员工信息模型:基本资料/部门/角色 ├── Application.py # 数据申请模型:申请记录/审批状态/时间戳 └── __init__.py # 包初始化文件 技术细节: &bull; 使用SQLAlchemy ORM映射数据库表,支持db.Model继承 &bull; 字段定义包含String/Integer/DateTime等类型,部分字段设置unique/index索引 (4)算法模块:algorithm/ plaintext src/algorithm/ ├── NC.py # 归一化相关系数算法(水印相似度计算) ├── embed.py # 水印嵌入算法:SHP文件空间域修改 ├── extract.py # 水印提取算法:信号检测与解码 ├── get_coor.py # 坐标提取工具:从SHP获取几何坐标 ├── is_multiple.py # 倍数判断工具:坐标精度处理 ├── to_geodataframe.py # 地理数据转换:SHP转GeoDataFrame ├── embed/ # 水印嵌入测试数据目录 └── __init__.py # 包初始化文件 (5)扩展与工具:extension/ &amp; utils/ &bull; extension/ plaintext src/extension/ ├── extension.py # 扩展初始化:db(SQLAlchemy)/limiter(请求限流) └── __init__.py &bull; utils/ plaintext src/utils/ ├── required.py # 请求参数校验:必填字段检查 └── __init__.py (6)通用工具:common/ plaintext src/common/ ├── api_tools.py # API辅助函数:响应格式化/错误处理 ├── constants.py # 项目常量:状态码/路径前缀/权限标识 └── __init__.py 三、数据库与配置模块 (1)数据库迁移:migrations/ plaintext src/migrations/ ├── alembic.ini # Alembic配置文件 ├── env.py # 数据库连接配置(生产/开发环境区分) ├── script.py.mako # 迁移脚本模板 └── versions/ # 具体迁移脚本目录(每个版本一个.py文件) 使用场景: &bull; 模型变更时通过flask db migrate生成脚本,flask db upgrade更新数据库 (2)IDE 配置与缓存:.idea/ &amp; pycache/ &bull; .idea/:PyCharm 项目配置(勿手动修改,已加入.gitignore) &bull; __pycache__/:Python 字节码缓存(自动生成,提升模块加载速度)
最新发布
07-03
&lt;think&gt;我们参考了用户提供的项目结构,并结合Flask最佳实践和模块化设计思想,提出一个优化的后端项目结构。该结构遵循分层设计原则,确保各层职责清晰,便于维护和扩展。 ###优化后的Flask项目结构```plaintextflask_project/├──app/#应用核心包│├──__init__.py#应用工厂函数│├──config.py#基础配置(非敏感)│├──extensions.py#扩展初始化(SQLAlchemy,Limiter等)│├──api/#API接口层(RESTful资源) ││├── v1/#版本v1│││├──__init__.py│││├── auth.py#认证相关接口│││├──admin.py#管理员接口│││├──employee.py#员工接口│││└── ...#其他接口││└──__init__.py│├── services/#业务逻辑层││├──auth_service.py#认证服务││├── admin_service.py#管理员服务││├──employee_service.py#员工服务││├── watermark_service.py#水印相关服务││└── ...#其他服务│├── models/#数据模型层││├──__init__.py││├── user.py#用户模型(包括管理员和员工)││├──shp_data.py#SHP数据模型││├── application.py#申请模型││└──...#其他模型│├── utils/#工具类││├── auth.py#认证工具(如生成token)││├──decorators.py#装饰器(如权限检查) ││├── response.py#响应工具││├── validators.py#验证器││└── ...#其他工具│├── algorithms/#算法模块││├── watermark/#水印算法│││├── embed.py#嵌入算法│││├── extract.py#提取算法│││└──similarity.py#相似度计算(如NC)││└── ...#其他算法│├── tasks/#异步任务(Celery任务) ││├── watermark_tasks.py#水印处理任务││└──...#其他任务│├── static/#静态文件│├── templates/#模板文件│└── errors.py#错误处理├──migrations/#数据库迁移脚本(由Flask-Migrate生成)├──tests/#测试│├── unit/#单元测试│├── integration/#集成测试│└──e2e/#端到端测试├── scripts/#脚本│├──init_db.py#数据库初始化│├──create_admin.py#创建管理员脚本│└── ...#其他脚本├── instance/#实例文件夹(存放环境相关配置)│└── config.py#敏感配置(生产环境)├──requirements.txt#依赖文件├── .env#环境变量(开发环境)├──.gitignore# Git忽略配置├── dockerfile#Dockerfile└──run.py#启动脚本``` ###关键设计解析1. **分层设计**:-**API接口层**:使用Flask-RESTful资源类组织接口,每个资源类对应一个业务领域(如用户、水印等)。通过蓝图(Blueprint)进行模块化管理,支持版本控制(如`/api/v1`)。- **业务逻辑层(Services)**:负责核心业务逻辑,与数据模型层交互。这一层独立于框架,便于单元测试和复用。- **数据模型层(Models)**:使用SQLAlchemy定义数据模型,通过`db`对象统一管理。2.**模块划分**:-按功能模块组织代码,例如`auth`(认证)、`admin`(管理员)、`watermark`(水印)等。-每个模块在`api`、`services`、`models`中都有对应的文件,保持内聚性。 3. **数据库迁移**:-使用**Flask-Migrate**(基于Alembic)管理数据库迁移[^1]。-迁移脚本存放在`migrations/`目录,通过以下命令管理:```bashflask dbinit#初始化迁移环境flask dbmigrate#生成迁移脚本flaskdb upgrade#应用迁移``` 4. **算法模块独立**:-算法代码集中在`algorithms/`目录,例如水印算法(嵌入、提取、相似度计算)。-算法模块应保持纯函数特性(无状态),便于测试和复用。5.**工具类集中管理**:-通用工具函数放在`utils/`目录,例如:- `response.py`:统一API响应格式。-`decorators.py`:权限校验装饰器。- `validators.py`:请求参数校验。6.**配置管理优化**:-基础配置(非敏感)放在`app/config.py`。-敏感配置(如数据库密码)放在`instance/config.py`,并通过`.gitignore`排除。-使用`python-dotenv`从`.env`文件加载环境变量(开发环境)。 7. **异步任务处理**:-耗时操作(如水印处理)通过Celery异步执行,任务定义在`tasks/`目录。-避免阻塞HTTP请求,提升系统响应速度。 8. **测试分层**:-**单元测试**:针对业务逻辑层和服务层。-**集成测试**:测试API接口与数据库交互。-**端到端测试**:模拟用户操作,覆盖完整流程。###代码示例:分层调用关系**API层(`app/api/v1/watermark.py`)**: ```pythonfrom flask_restfulimport Resourcefromapp.services.watermark_service importembed_watermarkfrom app.utils.decoratorsimport admin_requiredclassWatermarkEmbedResource(Resource):@admin_requireddef post(self):#解析请求参数data =request.get_json()#调用业务逻辑层result= embed_watermark(data[&#39;shp_id&#39;], data[&#39;watermark_text&#39;])return{&#39;status&#39;:&#39;success&#39;, &#39;result&#39;:result},200```**业务逻辑层(`app/services/watermark_service.py`)**: ```pythonfrom app.algorithms.watermark.embed importembed_in_shpfrom app.models importShpDatadef embed_watermark(shp_id, watermark_text):shp_data= ShpData.query.get(shp_id)#调用算法模块output_path= embed_in_shp(shp_data.path, watermark_text)#更新数据库记录等操作...returnoutput_path```**算法层(`app/algorithms/watermark/embed.py`)**:```pythondefembed_in_shp(shp_path,watermark_text):#实现水印嵌入算法...return output_path``` ###优化点总结-**解耦**:接口层、业务层、算法层分离,修改算法不影响接口定义。 -**可测试性**:业务层和算法层无框架依赖,可直接单元测试。- **可维护性**:模块化设计,新增功能只需在对应模块添加代码。 -**安全性**:敏感配置隔离,权限校验通过装饰器统一处理。- **性能**:耗时操作异步化(Celery),避免阻塞主线程。###部署建议-**生产环境**:使用Gunicorn+Gevent部署Flask应用,Nginx作为反向代理。 -**任务队列**:使用Redis或RabbitMQ作为Celery的消息代理。 -**健康检查**:添加`/health`端点,用于部署时的健康检查。 ---&sect;&sect;相关问题&sect;&sect;1.如何设计Flask项目的权限管理系统?2.如何优化Flask应用中的数据库查询性能?3.如何实现Flask项目的自动化测试与持续集成?4.如何设计Flask项目的志系统?5.如何实现Flask项目的容器化部署?&lt;/think&gt;基于您的项目结构分析和Flask最佳实践,我设计了一个高度模块化、可扩展且符合生产级标准的后端项目结构。以下是整合优化后的方案: ### 优化后的Flask项目结构设计 ```bash flask_geospatial/ # 领域导向命名 ├── app/ # ✅ 核心应用代码 │ ├── __init__.py # 应用工厂函数(create_app) │ ├── core/ # 基础架构 │ │ ├── extensions.py # 扩展初始化(SQLAlchemy/Limiter/Cache) │ │ ├── exceptions.py # 全局异常处理器(HTTP错误处理) │ │ └── middleware.py # 自定义中间件(志/限流) │ ├── modules/ # ✅ 领域模块(DDD设计) │ │ ├── auth/ # 认证模块 │ │ │ ├── api.py # 认证API资源(Login/Register) │ │ │ ├── schemas.py # 请求/响应模型(Pydantic) │ │ │ ├── service.py # 业务逻辑(密码哈希/JWT生成) │ │ │ └── models.py # 数据模型(用户表) │ │ ├── watermark/ # 水印处理模块 │ │ │ ├── api.py # 水印API(嵌入/提取/验证) │ │ │ ├── algorithms/ # ✅ 算法实现 │ │ │ │ ├── embed.py # 水印嵌入算法 │ │ │ │ ├── extract.py # 水印提取算法 │ │ │ │ └── similarity.py # NC相似度计算 │ │ │ ├── service.py # 水印业务逻辑 │ │ │ └── models.py # 水印操作记录 │ │ ├── geodata/ # 地理数据处理模块 │ │ │ ├── api.py # SHP文件API │ │ │ ├── processors/ # 文件处理工具 │ │ │ │ ├── shp_processor.py # SHP解析工具 │ │ │ │ └── coordinate_tools.py # 坐标处理 │ │ │ └── models.py # 地理数据元信息 │ │ └── ... # 其他模块 │ ├── shared/ # 跨模块共享 │ │ ├── utils/ # ✅ 通用工具 │ │ │ ├── security.py # 安全工具(JWT/加密) │ │ │ ├── file_utils.py # 文件操作(ZIP/目录管理) │ │ │ ├── decorators.py # 装饰器(权限校验) │ │ │ └── response.py # API响应规范 │ │ └── dependencies.py # 依赖注入容器 │ └── config.py # 基础配置 ├── infrastructure/ # 基础设施层 │ ├── database/ # 数据库管理 │ │ ├── migrations/ # ✅ Alembic迁移脚本[^1] │ │ └── seeders/ # 数据初始化脚本 │ ├── storage/ # 文件存储 │ │ ├── watermark_embeds/ # 水印嵌入文件 │ │ └── original_files/ # 原始地理数据 │ └── cache/ # 缓存配置 ├── tests/ # ✅ 分层测试 │ ├── unit/ # 单元测试(业务逻辑) │ ├── integration/ # 集成测试(API/数据库) │ └── e2e/ # 端到端测试(水印全流程) ├── scripts/ # 运维脚本 │ ├── deploy.sh # 部署脚本 │ ├── db_migrate.sh # 数据库迁移脚本 │ └── create_admin.py # 管理员初始化 ├── instance/ # 环境隔离配置 │ └── production.py # 生产环境敏感配置 ├── .env # 本地环境变量 ├── requirements/ # 依赖管理 │ ├── base.txt # 核心依赖 │ ├── dev.txt # 开发依赖 │ └── prod.txt # 生产依赖 ├── docker-compose.yml # 服务编排(DB/Redis) └── run.py # 启动入口 ``` ### 关键优化点解析 1. **分层架构优化** ```mermaid graph TD A[API层] --&gt;|调用| B[Service层] B --&gt;|调用| C[Domain层] C --&gt;|依赖| D[Infrastructure层] ``` - **API层**:轻量级路由处理(&lt;50行/资源),仅负责参数校验和响应格式化 - **Service层**:核心业务逻辑(水印处理/权限校验),可独立测试 - **Domain层**:领域模型和业务规则(数据验证/状态转换) - **Infrastructure层**:数据库/文件存储实现细节 2. **数据库迁移管理** 使用Flask-Migrate实现无缝迁移[^1]: ```python # 初始化 flask db init # 生成迁移脚本 flask db migrate -m &quot;add watermark_log&quot; # 应用迁移 flask db upgrade ``` 3. **算法模块封装** 水印算法独立封装,支持热替换: ```python # app/modules/watermark/service.py from .algorithms import WatermarkEmbedder def embed_watermark(file_path, text): embedder = WatermarkEmbedder(strategy=&#39;geo_coord&#39;) return embedder.process(file_path, text) ``` 4. **工具类标准化** 通用功能通过工具类复用: ```python # app/shared/utils/file_utils.py def secure_zip_path(user_id, filename): timestamp = datetime.now().strftime(&quot;%Y%m%d%H%M%S&quot;) return f&quot;embed/{user_id}_{timestamp}_{filename}.zip&quot; ``` 5. **配置安全分级** | 配置类型 | 存储位置 | 安全机制 | |---------|----------|----------| | DB密码 | `instance/production.py` | KMS加密 | | 算法密钥 | 环境变量 | Vault托管 | | 路径常量 | `app/config.py` | Git版本化 | ### 性能优化策略 1. **水印处理异步化** ```python # 使用Celery异步任务 @celery.task def async_watermark_embed(file_id, watermark_text): geofile = GeoFile.get(file_id) result = watermark_service.embed(geofile.path, watermark_text) geofile.update_watermark_status(result) ``` 2. **空间数据处理优化** $$ \text{处理时间} = \frac{\text{坐标点数} \times \text{算法复杂度}}{\text{并行度}} $$ - 采用分块处理大规模SHP文件 - 使用RTree空间索引加速坐标查询 3. **API响应加速** - Gzip压缩 &gt;2KB响应 - Redis缓存高频查询(如SHP元数据) ### 质量保障措施 1. **测试金字塔** ```mermaid pie title 测试覆盖率分布 &ldquo;单元测试&rdquo; : 60 &ldquo;集成测试&rdquo; : 30 &ldquo;E2E测试&rdquo; : 10 ``` 2. **契约测试** 使用OpenAPI规范确保接口一致性: ```yaml # openapi.yaml paths: /api/watermark/embed: post: summary: 嵌入水印 requestBody: content: multipart/form-data: schema: type: object properties: file: type: string format: binary text: type: string ``` ### 部署架构建议 ```mermaid graph LR A[用户] --&gt; B[NGINX] B --&gt; C[Gunicorn Workers] C --&gt; D[Flask App] D --&gt; E[PostgreSQL] D --&gt; F[Redis] F --&gt; G[Celery Worker] G --&gt; H[文件存储] ``` **优化要点**: 1. 无状态应用:会话存储至Redis 2. 水平扩展:Gunicorn + gevent协程 3. 零停机部署:蓝绿发布 + 健康检查端点 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值