From 711e08af26e1746c0e84e2d65e539b8b79bc1d32 Mon Sep 17 00:00:00 2001 From: Estom Date: Tue, 14 Sep 2021 16:58:57 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E7=AE=80=E5=8E=86=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 工作日志/2021年9月1日-简历说明.md | 223 +++++++++++------------- 工作日志/image/2021-09-13-12-26-27.png | Bin 0 -> 11068 bytes 工作日志/image/2021-09-13-12-26-42.png | Bin 0 -> 11129 bytes 工作日志/image/2021-09-13-12-27-24.png | Bin 0 -> 3709 bytes 数据结构/6.1.cpp | 9 +- {数据结构 => 文献阅读}/6.11 树状数组.md | 0 6 files changed, 103 insertions(+), 129 deletions(-) create mode 100644 工作日志/image/2021-09-13-12-26-27.png create mode 100644 工作日志/image/2021-09-13-12-26-42.png create mode 100644 工作日志/image/2021-09-13-12-27-24.png rename {数据结构 => 文献阅读}/6.11 树状数组.md (100%) diff --git a/工作日志/2021年9月1日-简历说明.md b/工作日志/2021年9月1日-简历说明.md index f7170eb8..fc107f46 100644 --- a/工作日志/2021年9月1日-简历说明.md +++ b/工作日志/2021年9月1日-简历说明.md @@ -1,69 +1,71 @@ # 简历说明 -* [ ] 需要在面试开始前,花一天时间对简历说明进行整理 -* [ ] 项目和实习经历再熟悉。必须重新阅读一边原先的文档。 - - ## 1 教育经历 你好。我叫殷康龙,现就读于北京航空航天大学计算机学院,主要研究联邦学习在恶意软件检测领域的应用。本科就读于西北工业大学软件与微电子学院,主修软件工程。 -在学校主要学习了数据结构与算法、C++程序设计、JavaEE企业级开发、面向对象程序设计、编译原理等课程,综合测评成绩在250人中排名第8。 +在学校主要学习了C++程序设计、数据结构与算法、面向对象程序设计,综合测评成绩在250人中排名第8。 ## 2 校园经历 -在学校里积极参加社团和活动。曾任软微学院科创部干事,参与组织一行代码大赛和程序设计比赛。曾任西工大新闻中心副部长,负责开发新文中心的功能网站,培训技术人员,维护西工大官方微信。 +在学校里积极参加社团和活动。曾任软微学院科创部干事,组织一行代码大赛和程序设计比赛。曾任西工大新闻中心副部长,负责开发新文中心的功能网站,培训技术人员。 ## 3 主要成果 -* 两次学校一等奖学金,一次华为奖学金,一次国家励志奖学金,一次电子工业出版社助学金,“优秀共青团员”称号 -* 2016-2017年连续两届FIRA机器人世界杯SimuRoSot项目国际特等奖(冠军),Air Challenge项目国际一等奖(亚军) -* 2017中国机器人大赛空中机器人-无人机大战水果项目一等奖 -* 2019年获得国家级大学生创新项目《基于超宽带定位技术的无人机目标追踪系统》和《基于网络爬虫和数据分析的高校信息整合系统》优秀结题 -* 获得《面向学生的校园信息交流系统V1.0》《基于scrapy框架的校园信息爬虫系统》《基于网络爬虫和数据分析的高校信息整合系统》计算机软件著作权 +* 校一等奖学金,华为奖学金,国家励志奖学金,电子工业出版社助学金,“优秀共青团员”称号,优秀学生称号 +* 2016-2017年连续两届FIRA机器人世界杯、SimuRoSot项目国际特等奖(冠军),Air Challenge项目国际一等奖(亚军) +* 2017中国机器人大赛、无人机大战水果项目一等奖 +* 2019年获得两个国家级大创项目优秀结题、三个计算机软件著作权 ## 4 项目经历 > 项目概述、主要工作、最终成果 ### 竞技策略开发——仿真5VS5SimuRosot -* 项目概述:15个人的开发团队,长期开发项目,C++、JAVA,主要用于参加5V5 simurosot的国内比赛和国外比赛。工程主要采用分层架构, +* 项目概述:15个人的开发团队,长期开发项目。C++。基于simurosot机器人仿真平台,在国内比赛和国外有相关比赛。工程主要采用分层架构: * 第一层是运动模型,包括球的运动模型和轮式机器人的运动模型。控制机器人的轮速,完成前进、后退、旋转等基本动作。 * 第二层是跑位动作,给定目标点,机器人通过基本动作,完成避障行为,以最快的速度到达目标点。 - * 第三层是击球动作,在跑位的基础上,考虑球的运动状态,完成击球过程。 - * 第四层是策略控制,用于协调多个机器人,完成统一目标的动作。进行角色选择,向前场包括sender、defender、helper等角色。然后目标计算,分别计算每个机器人的目标点,选择机器人的运动方法。最后是策略切换控制,为了增强策略的稳定性,还包括策略的进入和退出控制。 + * 第三层是击球动作,在跑位的基础上,根据球的运动状态、击球者的运动状态、击球的目标方向等,完成击球过程。直接撞击、旋转甩球, + * 第四层是策略控制,用于协调多个机器人,完成统一目标的动作。进行角色选择,像前场包括sender、defender、helper等角色。然后目标计算,分别计算每个机器人的目标点,选择机器人的运动方法。最后是策略切换控制,为了增强策略的稳定性,还包括策略的进入和退出控制。 * 第五层是策略选择,包括态势评估,通过过去和当前的机器人和球的状态完成一系列态势分析,选择进入前场、后场、边路、底线等不同的策略中。 - * 另外还有一些辅助模块,包括日志模块,保存策略数据和运动数据,用于比赛复现和问题排查。态势预测模块,根据过去和当前的状态,预测未来一段时间内的态势,根据运动规律,计算未来球的位置。 - * 用到了一些基本的设置模式,像单例模式(小球的控制句柄、态势评估类的对象和态势预测的对象)、策略模式(给定统一接口) -* 主要工作1:负责开发前场的相关策略,分成很多子策略选择模块(优势前场、保守前场、边路前场)、角色选择和策略切换控制(角色的稳定性,进入退出分开控制。)、目标计算模块(保持相对的阵型,减少阵型的抖动)、移动跑位模块、射门模块。使用PID控制方法对机器人控制,增强了前场的稳定性。 -* 主要工作2:使用JAVA为团队开发了数据测试平台,实现了对数据仿真、策略测试、可视化。搭建团队开发的SVN版本控制系统,方便整个团队项目开发和维护。开发测试平台主要使用java swing开发跨平台图形界面,提供了一系列GUI组件。主要包括数据导入模块、动态演示模块、数据显示模块。使用java io random_accessfile读取并解析file文件。使用java thread实现数据加载与数据展示的并行过程。通过事件监听与响应机制,实现对数据仿真动态演示过程的控制,包括仿真速度调节和仿真进度调节。使用javadoc生成标准的java文档供后续开发使用,方便开发维护。 + * 辅助模块,包括日志模块。态势预测模块。 + * 设计模式:单例模式(小球的控制句柄、态势评估类的对象和态势预测的对象)、策略模式(不同策略、统一接口) + * 存在问题:策略的稳定性(最难的)。设置不同的严格的进入条件、宽松的退出条件,控制反转,每个策略类提供自己的进入退出条件和执行内容,然后注册成为一个策略树,由运行控制中心,负责执行策略树上的分支。IF-ELSE爆炸,将条件判断与条件执行分开、switchcase +* 主要工作: + * 负责开发前场的相关策略,构建子策略(优势前场、保守前场、边路前场)、角色选择和策略切换控制(角色的稳定性,进入退出分开控制。)、目标计算模块(保持相对的阵型,减少阵型的抖动)、移动跑位模块、射门模块。使用PID控制方法对机器人控制,增强了前场的稳定性。通过面向对象的方法对代码进行重构。 +* 主要工作:使用JAVA为团队开发了数据测试平台,实现了对数据仿真、策略测试、可视化。开发测试平台主要使用java swing开发跨平台图形界面,提供了一系列GUI组件。主要包括数据导入模块、动态演示模块、数据显示模块。使用java io random_accessfile读取并解析file文件。使用java thread实现数据加载与数据展示的并行过程。通过事件监听与响应机制,实现对数据仿真动态演示过程的控制,包括仿真速度调节和仿真进度调节。使用javadoc生成标准的java文档供后续开发使用,方便开发维护。 * 最终成果:暑假期间带领团队前往日照参加了2017中国机器人大赛,前往台湾 参加了FIRA机器人世界杯,取得多项冠军。 ### 基于网络爬虫和数据分析的高校信息整合系统 -* 项目概述:5个人,Python、MySQL。带领团队申请了《基于超宽带定位技术的无人机目标追踪系统》《基于网络爬虫和数据分析的高校信息整合系统》两个国家级大创项目,后者主要是利用爬虫综合网络信息,搭建web服务器,对数据进行二次处理,使用机器学习算法提供面向用户提供文章推荐功能、标签云索引功能和分类浏览功能,面向信息发布者提供了热点倾向功能、数据分析功能。 +* 项目概述:5个人,Python、MySQL。利用爬虫综合网络信息,搭建web服务器,对数据进行二次处理,使用机器学习算法提供面向用户提供文章推荐功能、标签云索引功能和分类浏览功能,面向信息发布者提供了热点倾向功能、数据分析功能。 + * 主要工作:项目架构、服务器搭建,包括爬虫模块(数据解析模块xpath、URL获取与去重模块)、服务器模块(MySQL数据库设计、Json数据封装)、Android客户端(数据请求模块HTTP请求、数据展示)、数据处理模块。通过Scrapy完成网络信息爬虫,构建了Mysql数据库,使用Django后端框架和Bootstrap前端框架开发了项目网站,使用大数据的算法对信息分析处理,并将整个项目部署到腾讯云提供的CentOS服务器上。使用Github进行代码管理。 -![](image/2021-04-06-21-18-56.png) * 关键技术:scrapy框架介绍。使用request模块进行爬虫,通过调度去缓存下一条URL,控制网站访问的频率;使用xpath解析数据内容并将数据存储到mysql数据库中。 -> * (1)Scrapy引擎打开,向爬虫模块请求其需要爬取的起始URLs -> * (2)Scrapy引擎从爬虫模块那里获取到需要爬取的起始URLs,将它们放入调度器模块,作为待爬取的URL Requests; -> * (3)Scrapy 引擎向调度器模块发出请求,获取下一个待爬取页面的URL; -> * (4)调度器模块返回下一个待爬取页面的URL给Scrapy 引擎,Scrapy 引擎则将该 URL 经下载中间件模块(请求方向)转发给下载器; -> * (5)当下载器模块完成页面下载后,会生成一个该页面所对应的 HTTP Response,并将其经下载中间件(响应方向)发送给Scrapy 引擎; -> * (6)Scrapy 引擎从下载器模块处接收到HTTP Response 后,会将其经爬虫中间件模块(输入方向)发送给爬虫模块处理; -> * (7)爬虫模块处理接收到的 HTTP Response,并返回从中爬取到的Items及需要跟进的新的 URLs 给 Scrapy 引擎; -> * (8)Scrapy 引擎将(爬虫模块返回的)Items 转发给数据流水线模块,同时将(爬虫模块返回的)URLs 转发给调度器; -> * (9)以上 2~8 的过程会一直重复执行,直到调度器模块中没有 URL Requests 时,Scrapy 引擎关闭,爬虫停止。 - -![](image/2021-04-06-21-06-32.png) * 关键技术:Django框架。使用Apache服务器,处理http请求。Django框架,MVC(model-view-control)的代码架构模式。从数据库中获取数据,封装成json格式,最后将响应的数据传递给android客户端。 -![](image/2021-04-06-21-17-24.png) -![](image/2021-04-06-21-58-13.png) -* 关键技术:数据处理算法。 - * 标签计算算法:jieba分词统计词频,TF-IDF算法进行词频统计,去除无关词汇,字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。 - * 分类算法:学科竞赛、科研信息、行政信息、招生信息、招聘就业、校园活动、升学留学、生活娱乐这八类,使用朴素贝叶斯分类器进行分类。(基于贝叶斯公式,可以试图讲解贝叶斯公式) - * 混合推荐算法:基于协同过滤算法提取项目的基本特征(人,文章的特征,通过人阅读的其他文章给出特征,通过相似的人看的其他电影打上相似的标签)。系统采用的KNN算法目的在于匹配项目中K个相似度最高的项目,作为预测推荐输出到用具接口。 +* 关键技术:* 标签计算算法:jieba分词统计词频,TF-IDF算法进行词频统计,去除无关词汇,字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。 + * 词频 (term frequency, TF) 指的是某一个给定的词语在该文件中出现的次数。逆向文件频率 (inverse document frequency, IDF) + ![](image/2021-09-13-12-26-27.png) + * IDF的主要思想是:如果包含词条t的文档越少, IDF越大,则说明词条具有很好的类别区分能力。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到。 + ![](image/2021-09-13-12-26-42.png) + * 标签云算法:某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。 + ![](image/2021-09-13-12-27-24.png) +* 关键技术:分类算法:学科竞赛、科研信息、行政信息、招生信息、招聘就业、校园活动、升学留学、生活娱乐这八类,使用朴素贝叶斯分类器进行分类。贝叶斯分类,一个事件出现在各个类别中的概率不同。可以通过贝叶斯公式得到,出现概率最大的类别作为其类别。 +``` +提取所有文档中的词条并进行去重 +获取文档的所有类别 +计算每个类别中的文档数目 +对每篇训练文档: + 对每个类别: + 如果词条出现在文档中-->增加该词条的计数值(for循环或者矩阵相加) + 增加所有词条的计数值(此类别下词条总数) +对每个类别: + 对每个词条: + 将该词条的数目除以总词条数目得到的条件概率(P(词条|类别)) +返回该文档属于每个类别的条件概率(P(类别|文档的所有词条)) +``` +* 关键技术:推荐算法:系统采用的KNN算法目的在于匹配项目中K个相似度最高的项目,用户浏览的历史文章,生成用户关联的词向量。 * 最终成果:两个国家级大创项目均获得优秀结题。 @@ -73,7 +75,66 @@ * 主要工作:主要是在Android平台(DJ无人机的地面站android手机开发),使用Java多线程和Socket编程,实现无人机之间的通信连接。主要通过UDP网络通信、心跳测试保持连接、回调处理等方式实现线程通信。在加密通信过程中,使用C++开发加密仿真环境。使用nodejs+electron对通信过程进行可视化。使用网页技术HTML、CSS、JavaScript做前端,使用C++做为本地的后端。通过封装C++通信的代码,提供C++通信接口,供nodejs调用。(代码的封装,接口提供,) * 主要成果:完成实验室项目验收。 -### TensorFlowIO优化 + +## 实习经历 +### 电子钱包JavaEE企业及开发项目 + +* 项目概述:在中科金财上市公司参与电子钱包项目的实习。 +* 主要负责使用Java从合作方获取并解析数据,使用MyBatis存储到MySQL数据库中,并使用Redis做一级数据缓存。使用Spring框架提供信息访问的服务。 +* 关键技术:Spring框架应用实践 + * 本项目后端的主要开发框架,是基于java的Spring框架。Spring框架主要依赖与两个重要的特性——控制反转和依赖注入。控制反转(IOC),即控制权的转移,将我们创建对象的方式反转了,以前对象的创建是由我们开发人员自己维护,包括依赖关系也是自己注入。使用了spring之后,对象的创建以及依赖关系可以由spring完成创建以及注入,反转控制就是反转了对象的创建方式,从我们自己创建反转给了程序创建。依赖注入(DI)spring这个容器中,替你管理着一系列的类,前提是你需要将这些类交给spring容器进行管理,然后在你需要的时候,不是自己去定义,而是直接向spring容器索取,当spring容器知道你的需求之后,就会去它所管理的组件中进行查找,然后直接给你所需要的组件。 + * 在实践过程中,使用静态工厂方法创建了一系列的java Bean对象,通过配置XML文件,将对象注入到具体执行的类当中。Spring框架本身还保证了事务的原子性、一致性、隔离性和持久性。为了使Spring boot应用能够快速加载配置,使用YAML文件快速配置Spring项目的依赖。YAML支持对象、数组、字面量三种数据结构。同时Spring boot通过大量的注解实现配置的绑定和容器的注入。 + * 在开发前端的时候,开发框架主要使用了基于nodejs的vuejs框架,用于获取并渲染数据到前端页面。使用bootstrap作为模板,构建基于H5的应用页面,能够动态自适应页面的大小,并将页面扁平化。 +* 关键技术:数据存储技术 + * 在开发过程中主要使用MySQL关系型数据库存储数据,使用Redis非关系型数据库做数据缓存,使用Spring-MyBatis框架,封装对数据库的增删查改操作。数据操作主要包括两部分,第一部分是从远程接口请求数据,存储到关系型数据库中。第二部分是从关系型数据库中访问数据,返回前端,渲染到页面上。对于第二部分需要Redis做一级缓存,为了加快数据访问。为了能够进行事务管理,MySQL的数据库引擎选择InnoDB。所有的表都保存在同一个数据文件中。 + * 使用Spring访问数据库的时候,选择了比较流行的MyBatis框架。MyBatis是一个半自动化的 ORM 框架,支持定制化 SQL、存储过程以及高级映射。支持将数据库查出的数据映射到POJO实体类上,而实体到数据库的映射则需要我们自己编写SQL语句实现 + * 为了提升用户的体验,加快前端的访问速度,解决MySQL数据库存储和访问的瓶颈。使用Redis数据库提供了以及数据缓存。使得系统能够快速相应用户的数据存储和访问操作。redis是一个开源的、使用C语言编写的、支持网络交互的、可基于内存也可持久化的Key-Value数据库。 + +### 字节跳动财经业务部 + +* 项目概述:实现担保交易的系统。 +* 主要负责财经退款业务。完成支付营销预计算、分账后退款等业务需求。基于Kite框架设计实现多个微服务的接口和逻辑,进行项目管理、版本控制、联调测试、报警处理等工作。 + * 当时负责支付营销预计算和分账后退款两个业务,涉及担保退款guarantee_refund(单纯的路由和参数校验)、退款请求ecrefund(查询校验请求参数,构造ectrade的不同类型的退款请求参数,请求计费系统,得到支付营销的值)、财经tp_ectrade(各种支付、退款的主要业务逻辑)微服务。担保退款业务负责接收来自其他应用的退款请求,查询数据库中的订单,校验请求的准确性,同时通过幂等校验对重复的请求进行处理。 + * 退款请求业务,接收担保退款微服务的请求,对请求进一步校验,根据订单状态、支付状态、业务方的需求将退款业务划分为不同的退款方式(急速退款、普通退款、分账后退款、超售后退款等),然后执行不同的退款逻辑。 + * 微服务的技术选型:服务注册与发现机制(consul)、敏捷开发流程(devops)、远程调用方式(thrift)、服务监控平台(Grafana)、数据分析平台(Hive)、链路系统跟踪平台、服务网关(Gateway)等。实现一系列微服务开发、部署、运维任务。 +* 关键技术:支付与退款业务逻辑 + * 在担保交易系统中,总的业务流可以分为四个部分:支付、分账、退款、提现。 + * 支付:当用户付款后(自有支付、第三方支付),不能立即存到商家的账户中,需要暂存到商家的待结算户中,防止出现资金安全问题。 + * 分账:当用户点击确认收款后,资金从商家的待结算户,分账到商家账户和其他分账方的账户(达人带货分账、平台营销分账等),其中还涉及到平台的营销问题。 + * 退款:当用户发起退款是,会根据不同的情况,走完全不同的退款流程,主要包括普通退款、分账前退款、分账后退款、超售后退款和急速退款。 + * 提现:商户从现金户中提款到自己的银行账户。 + * 针对退款:每一种退款都实现了统一的接口,需要校验大量的请求参数和订单内容,保证请求和订单的一致性,需要调用电商接口,计算每一个分账方的分账金额,根据分账方的分分钟金额校验账单系统中的分账单,针对每一个分账单,生成分账的退款单,然后请求支付核心,将商家待结算户中的金额退给用户。如果已经部分分账,需要将所有分账的金额退到商家现金户,推进分账进程,然后从商家的现金户,将金额退还给支付账户,并将平台补贴金额退回。每次退款过程前,需要事先请求计算支付营销金额,如果保证金额正确才可以进行后续的退款,否则返回退款失败。 +* 关键技术:订单模型。订单子系统,实现后端订单的数据流图。 + * 业务方可能会产生多种类型的订单,例如在购物的时候,会生成支付单、商户单、商品单等。 + * 退款的时候根据退款创建的时间不同,可能产生各种类型的退款单,通过区分是否在售后内或者超售后,是否满足优质用户的急速退款条件,订单是否已经分账,产生不同类型的退款单。在财经部分,根据业务方的需求,建立财经部分的订单系统,该系统主要融合了业务方订单和支付方订单。财经部分订单包括商品单、支付单、分账单、补贴单、退款单等。退款中会生成退款单包括多种类型,如退款子单、急速退款单、退分账单、退补贴单、退税单等。由于支付场景负责,各种订单的准确性必须要有保证。 + +* 关键技术:资金安全 + * 财经部分最重要的是对金额和流水的保证。建立了从上到下的对账系统,通过流水信息、数据库信息、日志信息等,进行不间断的对账,保证了交易金额的准确性。杜绝发生严重的金融风险。同时增强开发人员的金融管控意识。防止出现资金安全问题。 + +* 基于kite的微服务技术 + * 将后端拆解为多个独立的微服务,并行建设发展。很好地保证了各个模块的独立性,提高了开发效率,同时又由于微服务的弹性部署方式,使得系统的鲁棒性增强,服务的效率增高。 + * 微服务一种软件开发技术,服务是细粒度的,协议是轻量级的。使得应用系统具备快速响应、灵活部署、敏捷交付、持续演进的特性成为可能。微服务是由以单一应用程序构成的小服务,自己拥有自己的行程与轻量化处理,服务依业务功能设计,以全自动的方式部署,同时服务会使用最小的规模的集中管理能力,服务可以用不同的编程语言与数据库等组件实现 。 + * 微服务架构与敏捷研发流程一脉相承。微服务是将一个完整的系统分割成若干微小的、具备独立性的功能单元,每个功能单元是可以具备一个实际意义的小功能集。各个功能单元之间尽量是解耦或松耦合的,可以实现独立开发而不依赖其他功能单元。而敏捷保证微服务架构能够更好地适应需求的变化,保持团队的高效沟通,敏捷利用小型工作增量、频繁迭代与原型设计等手段,可以使我们摆脱大规模单体软件开发的风险。微服务架构更多地从技术的角度提升开发和运维的效率,而敏捷方法论贯穿了软件工程的整个流程,它重视流程、沟通、协作。可以说,敏捷在管理流程上是对微服务架构落地的有益补充和保障。微服务的开发大致遵循DevOps的流程和原则,一个软件从零开始到最终交付,大概包括以下几个阶段:规划、编码、构建、测试、发布、部署和维护。DevOps是一组过程、方法与系统的统称,用于促进开发、技术运营和质量保障(QA)部门之间的沟通、协作与整合。通过自动化流程来使得软件整体过程更加快捷和可靠。用于实现敏捷开发的目标。 + * 微服务主要面临的问题,主要是故障的排查,通过多方考虑建立了微服务的故障排查系统。首先是微服务的监控系统(指标接口),实时监控流量的运转,尽量能够快速的发现存在的潜在问题,包括一些设定的报警规则,如网络流量异常、内存占用异常、数据库链接异常、响应延迟异常、qps导致某个节点不堪重负等。让各个组件提供报告自己当前状态的接口(metrics接口),这个接口输出的数据格式应该是一致的。然后部署一个指标采集器组件,定时从这些接口获取并保持组件状态,同时提供查询服务。最后还需要一个UI,从指标采集器查询各项指标,绘制监控界面或者根据阈值发出告警。我们最终使用RedisExporter和MySQLExporter,这两个组件分别提供了Redis缓存和MySQL数据库的指标接口。微服务则根据各个服务的业务逻辑实现自定义的指标接口。然后采用Prometheus作为指标采集器,Grafana配置监控界面和邮件告警。 + * 通过链路跟踪系统,定位问题出现的位置。使用Zipkin工具,实现链路的跟踪过程,实现每一个节点的日志收集。为了能够快速的实现日志分析,使用ELK日志分析组件。包括一个日志搜索引擎、日志收集存储器和UI组件。为了能够控制微服务的访问权限,进行服务治理,搭建了一套网关系统。在调用者和被调用者中间加一层网关,每次调用时进行权限校验。另外,网关也可以作为一个提供服务接口文档的平台。能够进行各个微服务的接口管理,通过页面访问和调试微服务。 + * 微服务的注册和发现系统。每当有新的微服务或者微服务的某个新节点出现的时候,完成服务信息发布、存活检测、客户端负载均衡等任务。各个应用服务在启动时自动将自己注册到服务发现服务上。并且应用服务启动后会实时(定期)从服务发现服务同步各个应用服务的地址列表到本地。服务发现服务也会定期检查应用服务的健康状态,去掉不健康的实例地址。服务发现系统还会进行服务之间的负载均衡,防止某一个服务流量过大,称为微服务链路上的流量瓶颈。 + +## 5 个人能力 + +1. C++后端开发、熟悉Java/Go/Python/Nodejs、了解Mysql数据库/Redis数据库相关的知识 +2. 主要关于项目开发中某一方面的知识经验总结 + * 网络编程(各种语言的实现方法。异步并发,并发通信方式。) + * web开发(自己所开发过的web网站。主要用到的框架和技术。) + * 并发编程(各种语言实现并发编程的手段和方式,例如协程、多线程、多进程等) + +## 6 个人性格 + +1. 生活上,乐观开朗,心里素质较强。喜欢积极的应对生活中的困难。待人友善,团结合作,有较强的领导能力、组织能力和团队精神。勤奋好学,思维敏捷。 +2. 工作上,具有良好的专业能力,基础知识扎实,自学能力强。参与了多个项目的开发过程,具有丰富的项目开发经验。对软件工程领域的知识有很高的热情,希望通过自己的努力,创作完美的作品。 + + + +### 补充项目:TensorFlowIO优化 * 项目概述:分析TensorFlow源代码,对源代码进行修改重新编译。使用mmap方法,优化TensorFlow数据加载过程中的IO操作。 * 主要工作:阅读源代码分析TensorFlow架构,使用多线程以流的方式读取多个文件。mmap封装大文件读取过程。编译并测试TensorFlow最后的优化效果。 @@ -95,89 +156,3 @@ 5. 重新编译 * 最终成果:毕业答辩顺利完成。 - - -## 实习经历 -### 电子钱包JavaEE企业及开发项目 - -* 项目概述:在中科金财上市公司参与电子钱包项目的实习。 -* 主要负责使用Java从合作方获取并解析数据,使用MyBatis存储到MySQL数据库中,并使用Redis做一级数据缓存。使用Spring框架提供信息访问的服务。 -* 2.4 Spring框架应用实践 - * 本项目后端的主要开发框架,是基于java的Spring框架。Spring框架主要依赖与两个重要的特性——控制反转和依赖注入。控制反转(IOC),即控制权的转移,将我们创建对象的方式反转了,以前对象的创建是由我们开发人员自己维护,包括依赖关系也是自己注入。使用了spring之后,对象的创建以及依赖关系可以由spring完成创建以及注入,反转控制就是反转了对象的创建方式,从我们自己创建反转给了程序创建。依赖注入(DI)spring这个容器中,替你管理着一系列的类,前提是你需要将这些类交给spring容器进行管理,然后在你需要的时候,不是自己去定义,而是直接向spring容器索取,当spring容器知道你的需求之后,就会去它所管理的组件中进行查找,然后直接给你所需要的组件。 - * 基于这两种思想实现的Spring容器有许多好处,如降低组件之间的耦合度,实现软件各层之间的解耦。可以使容器提供众多服务如事务管理消息服务处理等等。当我们使用容器管理事务时,开发人员就不需要手工 控制事务,也不需要处理复杂的事务传播。容器提供单例模式支持,开发人员不需要自己编写实现代码。容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能。容器提供众多的辅佐类,使这些类可以加快应用的开发。Spring作为一个容器,可以管理对象的生命周期、对象与对象之间的依赖关系。可以通过配置文件,来定义对象,以及设置与其他对象的依赖关系。 - * 在实践过程中,使用静态工厂方法创建了一系列的java Bean对象,通过配置XML文件,将对象注入到具体执行的类当中。Spring框架本身还保证了事务的原子性、一致性、隔离性和持久性。Spring boot是Spring体系下,为了快速创建应用而提供的一套脚手架服务,用于快速创建网络应用。Spring AOP框架基于代理模式,同时运行时可配置;AOP框架主要针对模块之间的交叉关注点进行模块化。通过maven工具简单的创建Spring boot应用,通过starter中整合了该场景下各种可能用到的依赖,只需要在Maven中引入starter依赖,框架就能自动扫描到要加载的信息并启动相应的默认配置。Spring MVC 是 Spring 提供的一个基于 MVC 设计模式的轻量级 Web 开发框架,其本身就是 Spring 框架的一部分,可以与 Spring 无缝集成,性能方面具有先天的优越性,是当今业界最主流的 Web 开发框架之一。Spring boot创建一款开源框架,它提供了 spring-boot-starter-web来为 Web 开发予以支持。spring-boot-starter-web为我们提供了嵌入的Servlet容器以及Spring MVC的依赖,并为Spring MVC提供了大量自动配置,可以适用于大多数 Web 开发场景。 - * 为了使Spring boot应用能够快速加载配置,使用YAML文件快速配置Spring项目的依赖。使用YAML作为属性配置文件,YAML语法使用缩进表示层级关系,对大小写敏感。YAML支持对象、数组、字面量三种数据结构。同时Spring boot通过大量的注解实现配置的绑定和容器的注入。 - * 在部署过程中主要使用了WebJars,WebJars可以将Web前端资源(JS,CSS 等)打成一个个的Jar包,然后将这些Jar包部署到Maven中央仓库中进行统一管理,当 Spring Boot项目中需要引入Web前端资源时,只需将所需资源的pom依赖导入到项目中即可。 - * 在开发前端的时候,开发框架主要使用了基于nodejs的vuejs框架,用于获取并渲染数据到前端页面。使用bootstrap作为模板,构建基于H5的应用页面,能够动态自适应页面的大小,并将页面扁平化。 -* 2.5 数据存储技术 - * 在开发过程中主要使用MySQL关系型数据库存储数据,使用Redis非关系型数据库做数据缓存,使用Spring-MyBatis框架,封装对数据库的增删查改操作。数据操作主要包括两部分,第一部分是从远程接口请求数据,存储到关系型数据库中。第二部分是从关系型数据库中访问数据,返回前端,渲染到页面上。对于第二部分需要Redis做一级缓存,为了加快数据访问。 - * 为了能够进行事务管理,MySQL的数据库引擎选择InnoDB。所有的表都保存在同一个数据文件中,InnoDB表的大小只受限于操作系统文件的大小,一般为2GB。需要更多的内存和存储,会在内存中简历专用的缓冲池用于高速缓冲数据和索引。索引和数据紧密捆绑,索引无压缩,所以体积相对比较大。InnoDB引擎支持外键和索引,支持事务管理和数据库锁。能够保证数据库事务的原子性、一致性等,在三级锁协议下能够保证数据库的串行化访问。MySQL的数据类型主要包括三种:数值类型、字符串类型和时间日期类型。在设计过程中要特别注意,符合BNF范式,保证子段不可分,且不存在冗余。 - * 主要在数据库中创建了各种各样的表格,包括商品表(商品名称、类型、编号、价格、供应商、数量等子段)、订单表(订单类型、订单编号、父订单编号、支付单号、创建时间、当前状态、用户、商户、税费等子段)、用户表(用户名称、用户编号、平台金额、用户身份等子段)。每一张表格代表多个独立的实体,多个表格之间通过外键进行关联。 - * 为了加快数据的访问速度,在MySQL的数据表上创建了各种类型的索引。MySQL中常用的索引结构有:B+树索引和哈希索引两种。目前建表用的B+树索引就是BTREE索引。在MySQL中,MyISAM和InnoDB两种存储引擎都不支持哈希索引。只有HEAP/MEMORY引擎才能显示支持哈希索引。所以主要包括五种类型:唯一索引、主键索引、外键索引、普通索引,复合索引。通过建立索引能够有效的加快访问速度。B+树是一个平衡的多叉树,从根节点到每个叶子节点的高度差值不超过1,而且同层级的节点间有指针相互链接。在B+树上的常规检索,从根节点到叶子节点的搜索效率基本相当,不会出现大幅波动,而且基于索引的顺序扫描时,也可以利用双向指针快速左右移动,效率非常高MySQL 由连接池、SQL 接口、解析器、优化器、缓存、存储引擎等组成,可以分为三层,即 MySQL Server 层、存储引擎层和文件系统层。MySQL Server 层又包括连接层和 SQL 层。 - * 使用Spring访问数据库的时候,需要手动创建SQL语句,或者通过Spring提供的jdbc链接数据库,根据orm映射规则,自己封装数据库语句。我们在开发的时候,选择了比较流行的MyBatis框架。MyBatis是一个半自动化的 ORM 框架,支持定制化 SQL、存储过程以及高级映射。支持将数据库查出的数据映射到POJO实体类上,而实体到数据库的映射则需要我们自己编写SQL语句实现,相较于Hibernate 这种完全自动化的框架,Mybatis 更加灵活,我们可以根据自身的需求编写sql语句来实现复杂的数据库操作。支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架。它消除 了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis使用简单的XML或注解用于配置和原始映射,将接口和 Java 的 POJOs映射成数据库中的记录。利用动态语句的特性,方便快速的拼接访问数据库的SQL语句。 - * Mybatis的功能架构分为三层。API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。 - * 我们首先需要在Spring框架中导入Mybatis的配置在Spring Boot的配置文件中进行配置,指定mapper.xml的位置、实体类的位置、是否开启驼峰命名法等。然后配置数据库链接的信息。在MySQL数据库中创建了多张表,并创建了mapper文件,建立sql语句到java环境的映射,用来访问MySQL数据库。然后在配置文件中注册数据库访问xml,在Spring的java文件中引用该配置,完成对数据库的访问。 - * 为了提升用户的体验,加快前端的访问速度,解决MySQL数据库存储和访问的瓶颈。使用Redis数据库提供了以及数据缓存。使得系统能够快速相应用户的数据存储和访问操作。redis是一个开源的、使用C语言编写的、支持网络交互的、可基于内存也可持久化的Key-Value数据库。与MySQL关系型数据库不同,它没有持久话的文件,是暂存在内存中的数据库,没有固定的表结构。Redis数据库作为缓存数据库有许多优势。Redis主要用于以下两种场景:高性能场景,需要执行耗时特别久,且结果不频繁变动的 SQL,就特别适合将运行结果放入Redis缓存。后面的请求就去缓存中读取,使得请求能够迅速响应;高并发场景,在大并发的情况下,所有的请求直接访问数据库,数据库会出现连接异常。这个时候,就需要使用 Redis 做一个缓冲操作,让请求先访问到 Redis,然后逐步同步到关系型数据库中。 - * Redis支持丰富的数据类型,包括string,list,set,sorted set,hash。主要由以下几种底层数据类型实现:动态字符串类型,保存字符串的长度、字符串的每个元、buf 数组中未使用的字节数量,能够动态的增加长度,并减少重新分配内存的次数;双向链表,通过多个节点结构就可以组成双向链表。字典又称为符号表或者关联数组、或映射,是一种用于保存键值对的抽象数据结构。跳跃表是一种有序数据结构,它通过在每个节点中维持多个指向其它节点的指针,从而达到快速访问节点的目的。 - * Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。Redis以内存作为数据存储介质,所以读写数据的效率极高,远远超过数据库。以设置和获取一个256字节字符串为例,它的读取速度可高达110000次/s,写速度高达81000次/s。它速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)。支持事务,操作都是原子性。可用于缓存、消息、设置过期时间。Redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销。为了解决读写分离模型的缺陷,可以将数据分片模型应用进来。可以将每个节点看成都是独立的master,然后通过业务实现数据分片。 - * Redis有多种持久化方法,RDB方式在指定的时间间隔内,将内存中的数据集快照写入到磁盘。AOF方式以日志的形式记录服务器处理的每一个操作,服务器启动之初,读取文件,重新构建数据库。 - * Redis的底层架构决定了它的性能优势。内部实现采用epoll机制和简单的事件框架。epoll中的读、写、关闭、连接都转化成了事件,然后利用epoll的多路复用特性, 降低IO过程的延迟。 - - -### 字节跳动财经业务部 - -* 项目概述:实现担保交易的系统。 -* 主要负责财经退款业务。完成支付营销预计算、分账后退款等业务需求。基于Kite框架设计实现多个微服务的接口和逻辑,进行项目管理、版本控制、联调测试、报警处理等工作。 - -* 基于gRpc的微服务技术 - * 在开发后期,为了能够更好的适应项目夸大的需求,公司制定新的发展计划,基于grpc重构后端框架,将后端拆解为多个独立的微服务,并行建设发展。很好地保证了各个模块的独立性,提高了开发效率,同时又由于微服务的弹性部署方式,使得系统的鲁棒性增强,服务的效率增高。 - * 微服务一种软件开发技术,面向服务的体系结构(SOA)架构样式的一种变体,将应用程序构造为一组松散耦合的服务。在微服务体系结构中,服务是细粒度的,协议是轻量级的。使得应用系统具备快速响应、灵活部署、敏捷交付、持续演进的特性成为可能。微服务是由以单一应用程序构成的小服务,自己拥有自己的行程与轻量化处理,服务依业务功能设计,以全自动的方式部署,同时服务会使用最小的规模的集中管理能力,服务可以用不同的编程语言与数据库等组件实现 。 - * 微服务架构与敏捷研发流程一脉相承。微服务是将一个完整的系统分割成若干微小的、具备独立性的功能单元,每个功能单元是可以具备一个实际意义的小功能集。各个功能单元之间尽量是解耦或松耦合的,可以实现独立开发而不依赖其他功能单元。而敏捷保证微服务架构能够更好地适应需求的变化,保持团队的高效沟通,敏捷利用小型工作增量、频繁迭代与原型设计等手段,可以使我们摆脱大规模单体软件开发的风险。微服务架构更多地从技术的角度提升开发和运维的效率,而敏捷方法论贯穿了软件工程的整个流程,它重视流程、沟通、协作。可以说,敏捷在管理流程上是对微服务架构落地的有益补充和保障。微服务的开发大致遵循DevOps的流程和原则,一个软件从零开始到最终交付,大概包括以下几个阶段:规划、编码、构建、测试、发布、部署和维护。DevOps是一组过程、方法与系统的统称,用于促进开发、技术运营和质量保障(QA)部门之间的沟通、协作与整合。通过自动化流程来使得软件整体过程更加快捷和可靠。用于实现敏捷开发的目标。 - * 我们研究了微服务主要面临的问题,主要是故障的排查,通过多方考虑建立了微服务的故障排查系统。首先是微服务的监控系统(指标接口),实时监控流量的运转,尽量能够快速的发现存在的潜在问题,包括一些设定的报警规则,如网络流量异常、内存占用异常、数据库链接异常、响应延迟异常、qps导致某个节点不堪重负等。让各个组件提供报告自己当前状态的接口(metrics接口),这个接口输出的数据格式应该是一致的。然后部署一个指标采集器组件,定时从这些接口获取并保持组件状态,同时提供查询服务。最后还需要一个UI,从指标采集器查询各项指标,绘制监控界面或者根据阈值发出告警。我们最终使用RedisExporter和MySQLExporter,这两个组件分别提供了Redis缓存和MySQL数据库的指标接口。微服务则根据各个服务的业务逻辑实现自定义的指标接口。然后采用Prometheus作为指标采集器,Grafana配置监控界面和邮件告警。 - * 然后是通过链路跟踪系统,定位问题出现的位置。使用Zipkin工具,实现链路的跟踪过程,实现每一个节点的日志收集。为了能够快速的实现日志分析,使用ELK日志分析组件。包括一个日志搜索引擎、日志收集存储器和UI组件。为了能够控制微服务的访问权限,进行服务治理,搭建了一套网关系统。在调用者和被调用者中间加一层网关,每次调用时进行权限校验。另外,网关也可以作为一个提供服务接口文档的平台。能够进行各个微服务的接口管理,通过页面访问和调试微服务。 - * 由于微服务的扩充速度比较快速,最终搭建了一个微服务的注册和发现系统。每当有新的微服务或者微服务的某个新节点出现的时候,完成服务信息发布、存活检测、客户端负载均衡等任务。各个应用服务在启动时自动将自己注册到服务发现服务上。并且应用服务启动后会实时(定期)从服务发现服务同步各个应用服务的地址列表到本地。服务发现服务也会定期检查应用服务的健康状态,去掉不健康的实例地址。服务发现系统还会进行服务之间的负载均衡,防止某一个服务流量过大,称为微服务链路上的流量瓶颈。 - * 在实现微服务系统的时候,还考虑了大量的其他安全性可靠性内容。包括建立链路上的熔断机制,当多次访问一个服务失败时,应熔断,标记该服务已停止工作,直接返回错误。直至该服务恢复正常后再重新建立连接。建立了微服务的多级测试系统,服务本地的单元测试,整个服务的测试,端到端测试(覆盖这个服务调用链的测试)。 - * 在构建微服务系统的核心关键技术是gRpc。gRPC是由Google公司开源的一款高性能的远程过程调用(RPC)框架,可以在任何环境下运行。该框架提供了负载均衡,跟踪,智能监控,身份验证等功能,可以实现系统间的高效连接。另外,在分布式系统中,gRpc框架也有有广泛应用,实现移动端、浏览器等和服务器的连接。gRPC支持多种语言的实现,因此gRPC支持客户端与服务器在多种语言环境中部署运行和互相调用。gRPC使用ProtoBuf来定义服务,ProtoBuf是由Google开发的一种数据序列化协议(类似于XML、JSON、hessian)。ProtoBuf能够将数据进行序列化,并广泛应用在数据存储、通信协议等方面。压缩和传输效率高,语法简单,表达力强。 - * gRPC 的协议设计上使用了HTTP2。HTTP2 提供了连接多路复用、双向流、服务器推送、请求优先级、首部压缩等机制。可以节省带宽、降低TCP链接次数、节省CPU,帮助移动设备延长电池寿命等。gRPC主流分布式方案有以下三个etcd, zookeeper, consul,最终选择使用consul实现服务的注册与负载均衡的实现。 - * 我们通过proto文件定义了数据结构和服务接口。可以通过流模式实现服务器和客户端的调用。集成了TLS验证方法,用于识别客户端和服务器,增强通信的安全性。使用SSL/TLS协议对通信连接进行安全加密,是通过非对称加密的方式来实现的。在加密过程中:客户端想要向服务器发起链接,首先会先向服务端请求要加密的公钥。获取到公钥后客户端使用公钥将信息进行加密,服务端接收到加密信息,使用私钥对信息进行解密并进行其他后续处理,完成整个信道加密并实现数据传输的过程。客户端调用服务时,客户端gRPC库使用协议缓冲区,并编组(marshal)远程过程调用,该调用随后通过HTTP2来发送。在服务器端,请求解组(un-marshalled),使用协议缓冲区执行相应的过程调用。响应遵循从服务器到客户端的类似的执行流程。 -* 支付与退款逻辑处理 - * 作为电子钱包财经部分的核心业务,其最大的困难点在于业务场景的理解和负责业务需求的实现,技术上的难点通过之前的分析已经实现了。 - * 首先最大的难点是建立后端的订单子系统,实现后端订单的数据流图。业务方可能会产生多种类型的订单,例如在购物的时候,会生成shop单、商户单、商品单,退款的时候根据退款创建的时间不同,可能产生各种类型的退款单,通过区分是否在售后内或者超售后,是否满足优质用户的急速退款条件,订单是否已经分账,产生不同类型的退款单。在财经部分,根据业务方的需求,建立财经部分的订单系统,该系统主要融合了业务方订单和支付方订单。业务方订单包括shop单、sku单、商品单等,财经部分订单包括四种主要的类型,商品单、支付单、分账单、退分账单、补贴单、推补贴单、退款单等。退款中会生成退款单包括多种类型,如退款子单、急速退款单、退分账单、退补贴单、退税单等。由于支付场景负责,各种订单的准确性必须要有保证。 - * 财经部分最重要的是对金额和流水的保证。建立了从上到下的对账系统,通过流水信息、数据库信息、日志信息等,进行不间断的对账,保证了交易金额的准确性。杜绝发生严重的金融风险。同时增强开发人员的金融管控意识。防止出现资金安全问题。在技术上,使用GO语言重构了后端的微服务,包括一系列配套的微服务工具的应用。如上一节提到的微服务的技术选型:服务注册与发现机制(consul)、敏捷开发流程(devops)、远程调用方式(thrift)、服务监控平台(Grafana)、数据分析平台(Hive)、链路系统跟踪平台、服务网关(Gateway)等。实现一系列微服务开发、部署、运维任务。 - * 在担保交易系统中,总的业务流可以分为四个部分:支付、分账、退款、提现。当用户付款后(自有支付、第三方支付),不能立即存到商家的账户中,需要暂存到商家的待结算户中,防止出现资金安全问题。当用户点击确认收款后,资金从商家的待结算户,分账到商家账户和其他分账方的账户(达人带货分账、平台营销分账等),其中还涉及到平台的营销问题。当用户发起退款是,会根据不同的情况,走完全不同的退款流程,主要包括普通退款、分账前退款、分账后退款、超售后退款和急速退款。其中每一种业务都被划分为一个独立的微服务,可能部署在不同的虚拟机上,存在大量远程调用过程。 - * 当时负责支付营销预计算和分账后退款两个业务,涉及担保退款、退款请求、财经核心微服务,整个服务链包括十几个业务,我负责其中的三个。担保退款业务负责接收来自其他应用的退款请求,查询数据库中的订单,校验请求的准确性,同时通过幂等校验对重复的请求进行处理。退款请求业务,接收担保退款微服务的请求,对请求进一步校验,根据订单状态、支付状态、业务方的需求将退款业务划分为不同的退款方式(急速退款、普通退款、分账后退款、超售后退款等),然后执行不同的退款逻辑。每一种退款都实现了统一的接口,需要校验大量的请求参数和订单内容,保证请求和订单的一致性,需要调用电商接口,计算每一个分账方的分账金额,根据分账方的分分钟金额校验账单系统中的分账单,针对每一个分账单,生成分账的退款单,然后请求支付核心,将商家待结算户中的金额退给用户。如果已经部分分账,需要将所有分账的金额退到商家现金户,推进分账进程,然后从商家的现金户,将金额退还给支付账户,并将平台补贴金额退回。每次退款过程前,需要事先请求计算支付营销金额,如果保证金额正确才可以进行后续的退款,否则返回退款失败。 - -## 5 个人能力 - -1. C++后端开发、Java/Go/Python/Nodejs后端开发、Mysql数据库 -2. 主要关于项目开发中某一方面的知识经验总结 - - -* 网络编程(各种语言的实现方法。异步并发,并发通信方式。) - -* web开发(自己所开发过的web网站。主要用到的框架和技术。) - -* 并行编程(各种语言实现并发编程的手段和方式,例如协程、多线程、多进程等) - -## 6 个人性格 - -1. 乐观开朗,心里素质较强,喜欢积极的应对生活中的困难。待人友善,团结合作,有较强的领导能力、组织能力和团队精神。勤奋好学,思维敏捷,自学能力强。 -2. 具有良好的专业能力,基础知识扎实。参与了多个项目的开发过程,具有丰富的项目开发经验。对软件工程领域的知识有很高的热情,希望通过自己的努力,创作完美的作品。 - - -## 7 补充项目 - -### ~~补充项目——软件与微电子学院学生信息系统。PHPweb开发~~(----丢失) -* 项目概述:20个人组成的团队,PHP、MySQL。系统主要包括任务管理系统、证书认证系统、请销假平台、项目管理、活动,会议记录、党建系统、文件管理系统、就业记录等子系统。使用PHP作为后端开发脚本,使用MVCyii框架进行开发。 -* 主要工作:构建数据库。使用yii框架实现请销假平台,包括表单管理和MySQL数据库访问。yii框架是MVC结构。由controller处理逻辑内容,model封装数据库访问,view视图作为界面,用来渲染数据,发送到前端。 -![](image/2021-04-06-20-19-05.png) -* 最终成果:开发完成暑期项目实践,项目成功验收。 - - -### ~~补充项目——企业级开发JavaEE项目考试系统~~(√上传) -> 因为是java项目,等日后学完java再写 - -### ~~补充项目——windows通信编程。多人聊天室~~(√上传) -* 项目概述:单人项目开发。 -* 主要工作:MFC开发界面、windows网络通信。 -* 主要成果:课设。 \ No newline at end of file diff --git a/工作日志/image/2021-09-13-12-26-27.png b/工作日志/image/2021-09-13-12-26-27.png new file mode 100644 index 0000000000000000000000000000000000000000..3419c8ab350811cfec39c3df28f5ab0f5c3d013a GIT binary patch literal 11068 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 HHwye865nQ~ literal 0 HcmV?d00001 diff --git a/工作日志/image/2021-09-13-12-26-42.png b/工作日志/image/2021-09-13-12-26-42.png new file mode 100644 index 0000000000000000000000000000000000000000..01201feb2e0e3b6a735209baa0e5df18cea9f233 GIT binary patch literal 11129 zcmc(FV{j!v)9y(&8*Z!(H@1@#+qP|=*xV!=+qSKZZQHhOC*QvB_v_x@x9a|w>FKGN zs-Eeds_uE7Po{!fRo6W4GA01*2A)4+yoON;>kY6J;k0cAJci%fTIR56?(wj2Q} zG{3x1iX0jFP{q8YobUUV<;!7EIp_`k7iXYyw{4j-m8r&EFkK3NmFr$u_3z5yuptnC zAV?Gt0)-jDq!Y-{Z!gguVj!#;7km!ipjKASZCsKww|J+Rr^b=?9XKHVSpwMu{q;}& zW;prC0swv@~p!MeG@i)Wv0tul-Kb?{9y^Yz^0r#JU z9rhXvDDBJ0@EZ1^B19azit@3znY7c|rBLqPvWjW92u=`JM;RN-m!HZcSF-x5&W~AGNdK+~l+xNPjz}L(-BXr<6)IRb zW1#&C%tEAR6u?mUxrgz7KW7--d90cyjz6d}=CK>-GMuH0?p#l@OX{8SBaNYPsDOU2=FzQqtt+1|{nE828iJ4NWBRv7i3kO>i`EQg%mlGFSI%Yalt0xepd4 zRI!v~0V;nA(~z91nsRih&_lS57x9rsjzU2d||_=bBZW20eN<=5WtFB}yHH0cPq8*_YJ%gh$IuMXv#NRi)e$OG_8TGV6^AO?5mPo@3MN0}66xq6@yW!@ zosov(a1i$@v_D&UTbj*Z{my7wusCk21L@3Tt8m*_)_;+l^DP|F0v}-!+g2j=+>cU0 z14{E+4n4%>(4@Sn@QzTV!;;E$Ge*!3#L`Ft)C*O2;Xm@kA1G+sf3MGKh7S}dRKyaX z?)(*vslYANnAPTE6WLnVJ#6(7An0XpqL7hQ!d}ixv%FCxvu%u`awo3bH|Q)KnP)mS zz4Pn(21WERR^^T;Nf?)U`rurgWFn>kbMNIbGZj0Tl6q2-uv&*>Xh1N0k_ajI$JcBm z?=&v$b&6bjl95{R0hv(@_fVUJar0k^v%6obU-WJa4t5qC<=o4CA|mDU^v_%U>`Y83 zdJuql2FH7s`U^i5M3}BW6XmGNTV08iwRXS{C4f@A@BW*2bf#D4o0Cve523oo2z@4~ zpv{?{_s#2C`mFAU;WdpK^*;NCHRKAcEQ!Q%XTl|-ZHBi%I)`*AIQs;mZC3n`)E9+c z?LWF&ztq_tQ0#BX5n4ANfA-=q+M86TQQK#w&PSv(x{~=M%(ugLf%<2;h^TcVM-tczCg) ziR9LQe%7cri!Ocw3izUS(SrBv)wK=Cba=qcxmLH`dp(=W#ogaOYFqg>eMS!4;D(Rr ze%nMn%ILVnWg2_&b`k^DFta6vKo|J+A01cmA~JDdmFMiP}C z)coScNL^mRVuQv{M6bblTYh4GtEaFT$o2ft*`((quE#d5Xx0TI2d%y9jp2z#x^(ZK z>xm!$j`?2|!{~d&V-McU4sFLvhE#_S&e^N`ti3egZ}vFd&f@m6hcGwkX}*-`FsKpl zVR>S-oj`lVFz2dHiP%$BB0kuzi1Y;AT9c7xU!lpXNZ|v|C*n>=TW|Nma#%!Mb+i=af5_&G{d7B|Nq6io&qN4*yPSNz(f-Lft)7NW1oya3t>PXE!XXLzu??oO zUgI6~M3|fp1l&fVfxY*HLm@Rnc%${5%x};kzv5(+?=5ZJ;tCvSGlM+mErK&-#Jn(Uu`@HTdB+3CE-o{P9`oOOMs>~%4EMc-kKV$LiZ6`vSM1`V8VR8m)>zy zLYisw^c-vzIVS@%P(Ye+pPk!u6rcx*@`iMDnbmpDBB!QR%et>9D^uN_BLMH7eDioB zD}XC#J2I~Jmm(A{HMxUFXLTT58L6g@y0Ri9YVuG6hbYc%V??%@p;sEVtCedWRm=2; zi#c|$-K_Txr-d0-=#?JFpqH)XvvL>~Se!tB=!|}RW%bpmNXMAoGo%8jqCaurI0#%I z@mndIJZ?AFpGZ9TCOU9cT|KPdv_$$MgU)XO&wftI zCfiiV*tfUBF7Vo^p~84BQ0L#br9uK73deo5wbI8NIV1gP!-X}`AsWf-7>#R}qx&IH z$Fy{vRgtcpOD}%;TJKZu?r7^PM9AR1a1w+WEHQh@>WPg>$(;?)34Ne=MZ6U z>N}4GT5e@h!70;2?wBOTu=~4OW=1%N5N_rc`j!D>G){20{TX!evAnrL!>vTZoF}H2 z%;V@hR%NLX=FzS3ut5mUI{SIC>Ow355U^75sj-P)jD1zH6NZJqH1OS9P#VB#-*6n+ zWgOh$o0ijqmIZ9#|7Ciaf|DHRJ_MwQzT@coq_(e|M5)EG15;8Rri^<^I9P{fshkt* zcJnyyH+ebq?y15gmj2#V;h`f>gmdHz{*A;eA*bd^7{_^uV+DoOrq2jNmiQF}q8*gO zabm-dj;Wb2yCwX2t@k1sK(ySPihO;l5&D`fzZAXb!Ofq{YhAQ}iohbS75SWM5Mn#D z!uvN|lUB~aZkrO;ijJhpBH#hB03CDK$K1!3jkqEimS(F=*6}=D;LvE4|6q&x#;-%f z^%e*q_lTmdDpE)fwHpqYO`Uyk7r;2BNES`m2IvigK9&joz zm8&?fS#erbgcUfRgQORNMyQyY3RG4~NRCZQL;L0XX-E}6fG!}cWWIbH+EZ@|5q*~v zyBbBX&xdPh8?M5T*AbtEL8Rea_y}8pK2$CHXZA)fwt=OwG@4FYR5s;_>cHWvg)sjC ziygh`l$)H(GQ(J_7)hqYxJ8^8U9Q(SDKA@uizxaqd>w7t^I7d;mKR)?~}kw)4xQ0 zI=Gn(WG0Oca?%^_ZAGLbz%EhIX(8xZwsetC7YQK3yuqdkV(|L-2rwN_;hxzFkgaDX zwgizUu|S&(U1$nxuT#nA-IvMF8ZFVlX%!SE2hceUss2@T1+r?gjJL3J2zc_TBw+Y) zc!T3>DvDrvED3KG%pSqg-BuOAv=U3H8W;Ppz^0K~Fwy8At~1IW*Jbn_#%lNZTUXN~ z>i8UXimt!Y6Akz-$A>dQMQ8E8TAlahNZ3dQM?LRMe^!7)=|R$M*~0PLZ@To87AH+C z`*q#?kWl)jhu?Ol+=R9D=Dg|~3!|Aa7&&i^#aQcTUpG@jnSc>PHG4bzG&DUCQCSiI zjD#pu3*5zQm9nA_mL&+-;5ox@jU*RWOsg>k#olGvEC|(_oJiA@L)3!6i3Avp4pq3mIe>qa^7Ekb$SzF0(w=#Ve z+cz(=8iO)hZ&vk=>oA}jWk0iJGJkFh%*=iW$JBWpR<%`M$Js=D5Yt!vyjulpUlLNq z?s`NOvYEHLX`a zb!`YjEL9aDT2YmgxkSQBpPMtnD3dAjJz_W4La%b&6*FuoZqq1YH-&H7_O`N>(ddtX zb3pjKZJQ~+GZdVbMK9W+*aotpcd)wPUjIN85woriY7;C?h3>!Jr>Zy?)jqrZ6q)P79;hz-LTaZ5@ zLuYX2^Edd5Q2@0*3JsP(!fJMtWUspf z>~^NuHM&|nzV_!w0nl66K<{aLGtlo^4N~GP33g1w^^5%(-XS+0Wwe3h{7VV@&Npkn z{`JGOkPwG%WhH{l*d-<02H?d|q0QWwE;jZJmy z6EvonGEK?5^;t9%4JI($>E(7*eRK)i;4F&7H_6pOiRQy(&@QxyH&Hs!)xD#K@YF|t zR5-X-Rgjpu{U-G08A5dMuSoRA*UcQ!yK1ev(V~c4Xz3ct=5~!=EAc@LtYG$xHs)4t zi8ORspXI+Af%B26oOd?Vnap-IB=e*dr&v-9+!F69Ta}`YNk6DO)A+Nar*#BnyZaQL zbV=KAqJ=z@S{MDGcy>ALi@CYvx)%BP)xKDqde+{~_Gyr#xjHK2k3O{K`K$cwD|NOF zD!{vwr-yafC@*>OwqOGDs);N4lm<@)Z80I8e6j|38h|o$fl7XdU+%4ynqJ<)n#VmR z5kl`3g!%WTB4)&+%&R}!QL22EN6U9pO1tyh>_a064 zO;^_8@kFJIVS!!@F49?r({}jmce~qK=DC!QjR$9Z%~qf)|FR!XsNQ zdtSO0Zy>tBTRMbL#@F3XTeoz(3wpcD6OPX7rt-PJ-qhotGg4EX=go|~o{nkPvpA4G zv8S`0zR(pWa84UwfbGhosa~U+jT&mHda_Qx;o6F#d#c@G?C7EsN#mF$yHp4c2n~c{ z^T>Av^L%7X?yis}pJ~<;Ar~^H$FM4IrMM zkfw4ARKPI_nbV-KRQ~)tO{DNdl^U+PjCx2KzaHnRk=1ISuRMeljNkSd3%?i(T%>9v zhH{fy#%Zv~wH|m+K;Dn}TUl8IZs%X1Hzc4ka{Kv@ghhBb@`}pWzgMvWizFH1zc)##rD@~h6rvD{Q9M5RXa2C!U3 zp~-0p&-x^VGQWQWmB7xZ=1&D#9-D4dmIR`9MV7tWEiM`jJ)KJ}0}DAgn4}wAfe@i^ zhM2M%9wLXWhF6_?Lq4|$SL*i{Wtm(q+F~9Yg70G5%gs0&PnD8#Pyk&-CafC=8*W7@ z_$!Bj9$ffgbCLxFtr>*CH4_f6-w0;Hw;@`;hr^I%?ntYl0RjhaNA5<_?=DLV9#)u^ z6yDxnf1&LA-QSX`dGszZ@Ebh1lN5ys+~u(4tWAanxBBPu3Nn|}cIRz>;TH1bKvmWcH8;HtMq>2w z^`z{UPwe+bb-iqCX)VeK0jky&r=#OXIIj>C);lHOci}!o*UP1xszibhVHzm^_hMOV zshH#uq^DTG7>i-41c`Z2ZSL+CpgX;%Hw^-LAEngNx*!}~tltEk5MF}LsjP}|4$UT6 zl0Xy>D?Jg$7YW)3YZ6z$UY7Z_nX?F#U8kPL`a0*rBWhlUM7%+pwL-O z;EX4bH3t3Hv$X|^fDLLRoBbh!b!LX+=oMyuiqPCWJmobc(&jS8bKimuYLo7>O+qiy zUSAv1= ze2%U07z#ljJYFyWH?H42;9e5n-9H}Sd(s`C>z_=@O2Cqm=0vtrJvEs_8EZ&%QjWPM zo~fKI=_~!Z9yHwiH|Tbn8@R!wnAz0*vuz4oXR|B>f9HZrl=x&>o}di+&X9QV7iGPJj-A`oy}-qT zxMCl55Z`@6n``$!L#BeyLU6~~TzsAZvZG`cGv@6e5f+WtZY4xT-HAvR4?3%r0VkCm?^UO`(-fLo;Bzz2VYr4|1CinA~=&IW59A6HZ zJhtWDmR=~7<4*DR5s>TZ9b-WxKuRuE>lRhSYBiae##6aKM7MHT;4UPf-RSyd*bAlX zkeh`1(tnr{Ludd_lE&=fr4p1OhPQXPjbxq4E&3XneSTzFJfK6x&CU9rkaQEXIUU22 zDLmSCe>P<{3$gJbxL6^N<*KL|pXv50sM~_X1SEbeion7-A3HAJF_N^Z!d>@aN>vi8 zafXMrtKf=>k$E=$DE+mj3=|EvHm|k&xU2(ltayIpT{H;|LY*QkJY!#IbITVN2Tge`me<%k(uZ(M$R_rhuv^13^ z{)A94Tt9c^;(@CN*aiuXj1`|D`r!*X|+uvlE&s_FtaFKXNcX65k zF$E~Aj!#&8@f&qFW6d7lx3I9QXpOD#E^%?*&gN=<6IAF}-9SCcTy^f0FIc59 z64%6b*mEJR;WQUX#2~?Im&jx@^LnEok;m;5_=(o+xxs>1JlJ-p2shO$jnixkuv@6qaX+^kSgYHzWU4C}HG8 z>muU1NzPw6RnbI*NRQ_8!mWL$u}*SE@P%G<^Ac6pAD;{tCUd9TN#*< zoEj0HUqN?(g$%O~qsUqjC35Bt_OnXmX*B>O96Ba7-4EAZAper%9CF?~!>iu@= zo0m`O!?TpbLZvGqjT2i1S5fO|_+Q#?EzG6}BgEU(K9PVel*}3#Y6vqvy+|i02#u2# zBgA&Isq5Q;0hj>O-l>Co=h=m$OWQdDH+^Q`sKF15?RDB)ZT77Xpy8b`rxDE?oth)K zAq>47M|cr7S=btQ*W;XJ0(zowp`l{`f3XGyl|WMY^|vG1Na=EsIEMY@b5{$KDo3H? z!w;WONlewla3EK$zHt)Ez*H1QfBx5c z=IoA=g&?AYI;$u#-Ez>U6D8%5^?5v{73S3W({otZ)c11T@f-a5q;ZG((_L3~Jq7{@ z+XtoN>h?~Gau?GYuG5{o?rH}w7}0+Sgl!JC$V5_ZAK&&KX~Z~j`Jo6+D7$LT*b@J{ zuoeB_-31pj(DWn@-K;QXsVZYHk5vsN_L2?E(#J13&HbfrD%p+jh_d?NfGg@wKJ)$( zcsINM;2K546}M$kj}WB4*Ky);So-1V^X~I5?=E&~EuGrRCy=~?V1$c>6-p1jDYL!W z_E4tOA02ODTzPLv6+#-J&7^3S*H~~p{K|ZIM`ZS+Oq}onR1SaGW3tM=XecOy`n z&>_N~j6Rz1oo^G7Ijs?R)KeN2o7{RGuOGzQPmcGYaf?B34Z_so;Mp3Vu?xZYh>s49 zCxcz?`+22%(D9hd9DRBNRqRevem%!e_;tmlBGtP4J|DH7%K<~~JwHE?>y~Y6m@9w1 zOL)ZA+Z$C*xf)sQgY^wfrSW)jchH-TN<5QV>*9I!51F`zr+YkL6kX}Mp1fSoWRaYl zT(m5H+I--I?{Q$ncR;q2PjYx}a2O}mOS&~=4V9H(3|ByEeUc(6V|*!y{G6F8dfTJs zTGVlSK|UDxm0=U$@ud=-$>hL6?IZ0C>>q29Gb4R9S$HTI1ryl(=J6SsuI+o}h8<4e z`V;j>Hh1TxvjC?W*rq{qak9l0XildyEC~il7%H}cY+cg{9jYW{|jjd?) z=jd6v$l6n}aiTKJz^vLaD~KXou{0`FO*7lHYANO5l=Q7PG~Jmh*z&;aG9*HZugPT8 zKl|=pC*&^^kH>=liC!Shy1T3iJ`SZ<77nZMmZ-0Yrh~(aakWKT-L-@=i!9(m>)A1@ zS%uDIsFJf{RZIOPk@d2;$Xr@l(UWwRzKH+o5A%87X}o)bLwskZ130hj$jwx2X+yy| zTqx;96ajjdFyGGCfPeSMaDg>QX*Z+_1Y`N8cAEYn$#!gVnz|^#H!Mu4tE*df=ifos zUGC9TDju=Z!oJQEH{4I_6*2w|jyUepbvlQ@IP(LTJ4)-NrM}kQQ6&2*(6}o)E=%q{ zx#4lT-dc+hy~l<-zD>p1&`WOs(XXKuuN_)NWEq7}&g?+4lk{|-9T@2qB1E7WmnLT& z)q2Iju`E$c2&u*2wzPruys=rrASog_KWU7Ai79@iv+Bl4T`U`se{+u?#Cy>5esKIwc@tp{kX?%_xEwgX3XV@K=WI^&f_<*y|A3d#I zl?|R+t!epvXv?N>^Pr!9{O?PcF{F~^64IqwV8(hE$?pnoSKEm!^}j^dAL3cUph?Po zk)~f<0bzFt#0MFpUbZ`7BLS^ul9e~p)Q}??Lb-}gk2T2)j*4={yr)kGu8tq$-z{gd z$ytqbLTieQ@iqJ>@j(YH_=}lmZ+$<#ZYa)DMowR0NXn zO8}LL*m~`j(7l4{vXW|Q>UfvzU4#e&j#5>VoW!RbEbOj|2y>q#G5W__ub=tioTe1_ zlyKpVxxQ;8)Lid~ZyMjCv?;K=)Vr^7&eNZ0cr9Sl2gT>-IcbExVa2mfDZjp8&!e+F zzCNoR`-ZBTcT&$G81u_=wSriEnP&^_GDd?4nTTa(jV9kW(nk=F}H z96y7Rx1eaLIHZKsosX+i@fyms^rEVN0~EZiJGyc*0sIK4Z!+y4N)~-AT3GU+rYbgC zdVj606O)PF)3fy$?g&nOB~evXSj_CM0v=hS{nD8H{E^`Q zL~G2MFZcc5`}bRS9FN-itc-nA$MaSQF@fIYwsYUwkkrBvrAd~T8)8Zx8aa(;v8Z^&9|Vq#Kz{UwB^rQ1;fWv+7QOw|g#w&e>*s}p+qTiJR2fT6Dh+G7 zrnSfoH1wOz4X!VuSe;;d1nvem#i3~Ouy53hyH3cJJT;N=ZX<=! z8YYSOAl>sfmt@?4pU)`{c~F6_S_J;9HT7ggG2sED%}a5ojjF{&E(dVKe^`HD@wHu< zpMC(fSa7191PfX;_1aba=-}!UX9wM_4zJ3Is%b~bp&+?%dZH|^@BKo}97S4%+92RW zW)Vm%2z+q4C*U7AO#;aqb=>{Z!ww{HmW}fG8;N#`QWHyX{hnq{W1jqGBcR6+MH=qHx9F2>pmQbeUZg)rT)Qlq5S>`WU9*G z#EXkmks&-j8grqV5DFrT+y6viTBVZy3z%R*b2or{$i7knoa zb2s4QF&>t3(Y=kT#w4}llpP#GQrj!-E5XafWJXC03ju&~b}LGa{oT{)7zXJ#)7@=8 z*tul7q;*Fo35H=HmKxK7WTwkF6LbD%JiHBMW{xGC9}6-mr5F+UtcX+dn8GoAD(H88 zW9-6@>|iu)>>6ygv}D;B2?F;9#qRTk{o!tRped5U6c9t4}Q^aDJnB2v#|?aUm`c%H9>!r#r}Qu zLiX?NXa8ZcI54~Q6c=ZIa^Q@YB-KFPf2waFr;~DA@meeHCN?|${>+L-EQeBV07XO($Xl(N5v8j zM;Med9ilQJL-z$&WocEQ_U4?BA4POm*L=5RVV?1AAR{Ip_e^wX`C3Qvo`V(m4pEG@vt&VMRupIC&f?Ax6UWd%Nmf9fy zIgl#p?~D_dhJu&%LCMQrY_dVPG)Q?+HgApHKekC6b}x#DNU1`mlm*2m4vB_0?W-f| z6GPItkUTHW<9kq~Qf2DDWc|0_x_2&L2BqN9+RX3gEYYfg!LQP+aN3XXnIM>>CPQcNf8jc< z>xBx>69_{x1(V3V)My0dY$YuG#{rNadqemTP$j_vdPRF1P34ri7PKhd10aA*kg(|? zV5(Oz$ij2(6j*d>a~|4y)nWDE#zpi_l7I9ed2#;cgYnsSZgaGRH$ERD9v+@=s>)(FSBu)_`+jI-quAdo5}x$lYh3TACH3o1`RsD864F64U zP*l-JHr9btZw#yW>7e$=Y#l!NO%(3~k)S+8uaH3&2b$0aY40k5=QKC+-5*-@|N$sg`Ux`x#2vSq%yZ6O^clo1+wE?zYG5 zd=2*BNq{HC^sEukJ+^q#;RN1KVYC+2+-8-}bWY8iDNQI&i>=bO8()iT@c%*tb^=8r zJY`Dd$FJN_tWZn2#m8|qk}Ds6Ef(3a-ze?O=~AK<83j5@oI=b;`-sI`U#1}bwVtyV zqUD3x5P0AgN9*2B$yGq+{DC6b_Lz94wen(QNytkLpHTtO2N?ywtrHRS+XEZUA?wIf zIMQ3FmG86QwCV!uLusx2rpuHm=xBo*JfQgdltY;BJyBfv?MiJNQlS^R|)F-{}12bbHe}t literal 0 HcmV?d00001 diff --git a/工作日志/image/2021-09-13-12-27-24.png b/工作日志/image/2021-09-13-12-27-24.png new file mode 100644 index 0000000000000000000000000000000000000000..fa66d8f962b90a632d22f31c3689a83ce44462a5 GIT binary patch literal 3709 zcmcJSX*3jW`^SgKmgrYmvnLUXOtvN=*&=JU7~9y##Ml|ik~J!18&h^;8^l-}A!JL) zI%5|N!`Rnh{yM+^o9FFw&U2r0-`Djy=li|Rb>HWHbHy6yYqB!)FarPpR&A|EMgRbf z`C0DFNPBknnD*n(0u9_qQw>n@;~Mb{=$uvcQ~`jhBo>Mt{TVa8(6WF702kZ;ZkjGw zvEy0tkM<)~lK`7FLZHcIe_Do(CoT?%DD3sdT+ee@rZSo%+S*SX_rC_2b`%7d)Lbol zO04(-DuJxJX}E(L`C(O9qq?{{tAf#rIAMdUlg!V)MvT)U(n%7n(nNU1Gp8`P<9DEt zN!#Yp2}M=5J+g0cKZ{IGXS&jUM;34ZO=d{~Z1BDoJnNMPAjk-K`H&p|2nPVz=>QMU z5OCK0+3f_+@a4Z6_A~r{4dcI-zZ$xKEq^t%|62ZPUj27vBQ zs0|Y*rLE2c;0#4rQhS@bX=nIQ9T6o;z7y6!$=FGj?MgaA5#199f}Wed<$j=z{9KOH zHuugYaRPk^DZ~Zg)OjIGVCYHfpTnj|dVgA*zCP3yH6~pf?`SOH6ev1ssA-s1CriY1 zMbh&Qln>|)vPg--MU`FGpWSVl4G;S{D|9*8DIwNC@oFL|=tuaXFPMpC=%(9Fb(nNa z;LqLyk(^-$8pK>X8nc%20OZkK3&)1sF%^+yVlu)mWXSLTyaKeFIOW`lTY8#t&+OX7 z)-?96JXvq*g~#Li%2D_FY#F`*EΠ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 I)NI5553xuGfdBvi literal 0 HcmV?d00001 diff --git a/数据结构/6.1.cpp b/数据结构/6.1.cpp index 9263b108..a14d7192 100644 --- a/数据结构/6.1.cpp +++ b/数据结构/6.1.cpp @@ -10,6 +10,9 @@ struct TreeNode{ TreeNode* left;//左子树 TreeNode* right;//右子树 TreeNode* parent;//可以不用 + // TreeNode(int v){ + // val=v; + // } }; class BinaryTree{ //TreeNode* root;//二叉树的根节点 @@ -35,8 +38,6 @@ public: int j=0; TreeNode* temp; while(!que.empty()){ - - if(que.front()==nullptr){ que.pop(); cout<<"\t"; @@ -61,8 +62,6 @@ public: cout<val<<" "; } - - //前序遍历 void pre_order(TreeNode*node){ if(node == nullptr){ @@ -106,7 +105,7 @@ public: que.pop(); } } - // 区分层次的层序遍历 + // 之字形区分层次的层序遍历 vector> levelOrder(TreeNode* root) { vector> vec; queue que[2]; diff --git a/数据结构/6.11 树状数组.md b/文献阅读/6.11 树状数组.md similarity index 100% rename from 数据结构/6.11 树状数组.md rename to 文献阅读/6.11 树状数组.md From 12464c187b6c8b9a14f086be4365a634dc618237 Mon Sep 17 00:00:00 2001 From: Estom Date: Wed, 15 Sep 2021 15:50:25 +0800 Subject: [PATCH 2/2] 123 --- 数据结构/6.1.cpp | 122 ++++++++++-- {文献阅读 => 数据结构}/6.11 树状数组.md | 0 数据结构/6.2.cpp | 244 ++++++++++++++++++++++++ 数据结构/6.8 堆树.md | 4 +- 数据结构/6.8.cpp | 12 +- 算法/A类:基本算法/1 算法概述.md | 4 +- 算法/A类:基本算法/3.1 查找算法.md | 2 +- 7 files changed, 361 insertions(+), 27 deletions(-) rename {文献阅读 => 数据结构}/6.11 树状数组.md (100%) create mode 100644 数据结构/6.2.cpp diff --git a/数据结构/6.1.cpp b/数据结构/6.1.cpp index 8b4d34fd..f41e3c08 100644 --- a/数据结构/6.1.cpp +++ b/数据结构/6.1.cpp @@ -1,8 +1,14 @@ //二叉树的链表实现 +/* +* 二叉树数组与链表表示的转换 +* 前序遍历(递归和非递归)、中序遍历(递归和非递归)、后序遍历(递归和非递归) +* 层序遍历(单队列单循环法。双队列双循环法) +*/ #include #include #include #include +#include using namespace std; struct TreeNode{ @@ -20,7 +26,7 @@ class BinaryTree{ public: // 创建二叉树 void build(TreeNode* &node,vector &vec,int i){ - if(i>vec.size() || vec[i]<0){ + if(i>=vec.size() || vec[i]<0){ return ; } node =new TreeNode(); @@ -72,6 +78,29 @@ public: pre_order(node->right); return; } + // 前序遍历非递归 + void pre_order_stack(TreeNode* node){ + // 左节点持续压栈,压栈访问。 + // 有节点退出时访问。 + stack st; + TreeNode* now = node; + TreeNode* temp; + while(!st.empty()|| now){ + while(now != nullptr){ + st.push(now); + process(now); + now = now->left; + } + // 这个判断防止栈为空,即一个节点也没有的情况。 + if(!st.empty()){ + temp = st.top(); + st.pop(); + now=temp->right; + } + + } + return ; + } //中序遍历 void mid_order(TreeNode*node){ if(node == nullptr){ @@ -82,7 +111,28 @@ public: mid_order(node->right); return; } - //后续遍历 + // 中序遍历非递归 + void mid_order_stack(TreeNode* node){ + // 左节点持续压栈,压栈访问。 + // 有节点退出时访问。 + stack st; + TreeNode* now = node; + TreeNode* temp; + while(!st.empty()|| now){ + while(now != nullptr){ + st.push(now); + now = now->left; + } + if(!st.empty()){ + temp = st.top(); + st.pop(); + process(temp); + now=temp->right; + } + } + return ; + } + //后序遍历 void lst_order(TreeNode* node){ if(node == nullptr){ return; @@ -91,6 +141,32 @@ public: lst_order(node->right); process(node); } + // 后序遍历的双栈法 + // 对于一个节点而言,要实现访问顺序为左儿子-右儿子-根节点,可以利用后进先出的栈,在节点不为空的前提下,依次将根节点,右儿子,左儿子压栈。故我们需要按照根节点-右儿子-左儿子的顺序遍历树,而我们已经知道先序遍历的顺序是根节点-左儿子-右儿子,故只需将先序遍历的左右调换并把访问方式打印改为压入另一个栈即可。最后一起打印栈中的元素。 + void lst_order_stack(TreeNode* node){ + stack st1; + stack st2; + TreeNode* now = node; + TreeNode* temp; + while(!st1.empty() || now){ + while(now){ + st1.push(now); + st2.push(now); + now=now->right; + } + if(!st1.empty()){ + temp = st1.top(); + st1.pop(); + now = temp->left; + } + } + + while(!st2.empty()){ + temp = st2.top(); + st2.pop(); + process(temp); + } + } // 层序遍历 void layer_order(TreeNode*node){ queue que; @@ -135,7 +211,8 @@ public: vec.pop_back(); return vec; } - // 区分层次的层序遍历2 改进版,单队列,单循环 + + // 区分层次的层序遍历2 改进版,单队列,单循环 vector> levelOrder2(TreeNode* root) { vector> res; vector vec; @@ -203,25 +280,38 @@ public: }; int main(){ //数组表示的树 - vector vec{9,8,7,6,-1,4,3}; + vector vec{1,2,3,4,5,6,7}; TreeNode n; TreeNode* node=&n; BinaryTree tree; tree.build(node,vec,0); // tree.display(node); + // 测试 + cout<<"preorder:"<> res = tree.levelOrder2(node); - for(auto a:res){ - for(auto b:a){ - cout<> res = tree.levelOrder2(node); + // for(auto a:res){ + // for(auto b:a){ + // cout< pre{3,9,20,15,7}; // vector mid{9,3,15,20,7}; diff --git a/文献阅读/6.11 树状数组.md b/数据结构/6.11 树状数组.md similarity index 100% rename from 文献阅读/6.11 树状数组.md rename to 数据结构/6.11 树状数组.md diff --git a/数据结构/6.2.cpp b/数据结构/6.2.cpp new file mode 100644 index 00000000..7bd05ea6 --- /dev/null +++ b/数据结构/6.2.cpp @@ -0,0 +1,244 @@ +// 二叉搜索树的创建和查找 +/* +* 二叉搜索树的插入、删除、查找 +*/ +#include +#include +#include +#include +#include +using namespace std; + +struct TreeNode{ + int val; + TreeNode* left;//左子树 + TreeNode* right;//右子树 + TreeNode* parent;//可以不用 + TreeNode(int v){ + val=v; + left = nullptr; + right = nullptr; + } +}; + +class BinarySearchTree{ +public: + + TreeNode* build(vector &vec){ + TreeNode* head = new TreeNode(vec[0]); + for(int i=1;ival<temp->val){ + if(temp->right!=nullptr){ + temp = temp->right; + } + else{ + temp->right = new TreeNode(val); + break; + } + } + else if(valval){ + if(temp->left!=nullptr){ + temp = temp->left; + } + else{ + temp->left = new TreeNode(val); + break; + } + } + } + } + // 递归插入叶子节点 + TreeNode* insert2(TreeNode* root,int val){ + if(root==nullptr){ + return new TreeNode(val); + } + if(valval){ + root->left = insert2(root->left,val); + } + else{ + root->right = insert2(root->right,val); + } + return root; + } + void insert(TreeNode* root,TreeNode* node){ + TreeNode* temp = root; + while(true){ + // cout<val<val>temp->val){ + if(temp->right!=nullptr){ + temp = temp->right; + } + else{ + temp->right = node; + break; + } + } + else if(node->valval){ + if(temp->left!=nullptr){ + temp = temp->left; + } + else{ + temp->left = node; + break; + } + } + } + return ; + } + void mid_order(TreeNode* root){ + if(root == nullptr){ + return ; + } + mid_order(root->left); + process(root); + mid_order(root->right); + return; + } + + + bool find(TreeNode* root,int val){ + TreeNode* temp = root; + while(temp){ + if(temp->val==val){ + return true; + } + if(val > temp->val){ + temp = temp->right; + } + else{ + temp = temp->left; + } + } + return false; + } + // 将左树上升。 + void delete_node(TreeNode* root,int val){ + TreeNode* new_root = new TreeNode(-1); + new_root->right = root; + TreeNode* temp = new_root; + TreeNode* parent=new_root; + + // 查找节点,如果存在则删除,不存在直接退出。 + bool left_or_right=false; + while(temp){ + if(temp->val==val){ + break; + } + if(val > temp->val){ + parent = temp; + left_or_right=true; + temp = temp->right; + } + else{ + parent = temp; + left_or_right=false; + + temp = temp->left; + } + } + if(temp==nullptr)return; + cout<<"left_or_right:"<left!=nullptr && temp->right!=nullptr){ + parent->left = temp->left; + TreeNode* t=temp->right; + while(t->left){ + t=t->left; + } + t->left = parent->left->right; + parent->left->right = temp->right; + } + else if(temp->left==nullptr){ + parent->left=temp->right; + } + else if(temp->right==nullptr){ + parent->left = temp->left; + } + } + else{ + if(temp->left!=nullptr && temp->right!=nullptr){ + parent->right = temp->left; + TreeNode* t=temp->right; + while(t->left){ + t=t->left; + } + t->left = parent->right->right; + parent->right->right = temp->right; + } + else if(temp->left==nullptr){ + parent->right=temp->right; + } + else if(temp->right==nullptr){ + parent->right = temp->left; + } + } + delete temp; + return; + + } + // 正常删除,找到右子树的最小节点,作为根节点。删除最小节点。 + // 非递归的方法实现,通过循环查找,循环删除 + void delete_node2(TreeNode* root,int val){ + TreeNode* new_root = new TreeNode(-1); + new_root->right = root; + TreeNode* temp = new_root; + TreeNode* parent=new_root; + while(temp){ + if(temp->val==val){ + break; + } + if(val > temp->val){ + parent = temp; + temp = temp->right; + } + else{ + parent = temp; + temp = temp->left; + } + } + + if(temp->left!=nullptr && temp->right!=nullptr){ + // 找到右子树的最小值。日后再来实现吧 + TreeNode* min_node=temp->right; + TreeNode* min_node_parent = temp; + while(temp->left!=nullptr){ + temp=temp->left; + } + } + } + void process(TreeNode* root){ + cout<val<<" "; + } +}; +int main(){ + vector vec{43, 10, 79, 90, 12, 54, 11, 9, 50}; + BinarySearchTree bt = BinarySearchTree(); + TreeNode* head = bt.build(vec); + cout<<"build&mid_order"< 类似于冒泡的思想,但是是一中更快的冒泡。保证最后能够建立最好的堆。 * 从根节点向叶节点开始,从前往后开始。进行多次上浮操作。 -* 从叶节点向根节点开始,从后往前开始。进行多次下沉操作。 +* 从后往前第一个非叶节点开始。进行多次下沉操作。 ### 插入(堆尾的数据) diff --git a/数据结构/6.8.cpp b/数据结构/6.8.cpp index 991ab7ee..a8e0a653 100644 --- a/数据结构/6.8.cpp +++ b/数据结构/6.8.cpp @@ -9,11 +9,11 @@ public: // cout<<111< max_queue; - // 创建堆 + // 创建堆。从第一个非叶节点开始向下调整 MaxQueue(vector vec) { max_queue=vec; - for(int i=vec.size()-1;i>=0;i--){ - shift_down((i-1)/2); + for(int i=vec.size()/2-1;i>=0;i--){ + shift_down(i); } } // 堆顶值.即队首的元素 @@ -98,9 +98,9 @@ public: }; int main(){ - // vector vec{0,1,2,3,4,5}; - // MaxQueue mq=MaxQueue(vec); - // mq.display(); + vector vec{0,1,2,3,4,5}; + MaxQueue mq=MaxQueue(vec); + mq.display(); // cout< 阅读目录 1. 顺序查找 2. 二分查找