软件设计中的一些原则介绍

软件设计原则介绍:

软件设计的目的:代码复用性、可扩展性、可维护性。

高内聚低耦合(High Cohesion & Low coupling)

高内聚,就是对软件系统中元素职责相关性和集中度高的功能放一起。在编写代码时,代码内的功能职责相关性高的放在一起。

与之相反 - 低耦合,低耦合是对元素与元素之间的连接、依赖的程度轻重描述。这里元素是指函数、类(对象),也可以指功能,系统,子系统,组件,模块等。

低耦合就是在编写软件时,尽量做到类与类、文件与文件、模块与模块,系统与系统之间尽量的独立存在,互不干扰。

DRY原则(Don't Repeat Yourself)

DRY 原则是指在代码设计编写中避免重复代码。

在代码编写中不应该出现重复的逻辑、属性等,对某些功能已存在代码应该重复使用,不应该在多个实例中拷贝相同的代码片段。

避免重复代码可以提高代码的可维护性,当需求变更时只需要在一处修改就能生效。

关注点分离(Separation of concerns,SoC)

在计算机编程里,关注点分离(Separation of concerns,SoC),是将计算机程序分隔为不同部分的设计原则,每一部分会有自己关注的焦点,围绕焦点来进行内容的聚集。

在编码设计中,体现关注点分离原则的有程序的模块化。区分关注的焦点,围绕与焦点相关的操作,把它们封装在具有明确边界的程序代码段中。

还有分层设计也体现了关注点分离这一原则,比如 MVC 分层,M 模型层、V 表示层、C 控制层 。

关注点分离的目的是要简化程序开发和维护。

KISS原则(Keep It Simple, Stupid)

kiss 原则(Keep It Simple, Stupid)就是简单优于复杂。

不管是程序设计还是系统设计都应该尽量保持简单,不要过度设计,不要增加无用功能,因为这些都可能导致系统复杂度增加。

面向对象的SOLID原则

单一职责原则(Single Responsible Principle, SRP)

单一职责原则(Single Responsibility Principle,SRP)又称单一功能原则,一个类或模块只负责一项功能和业务逻辑。马丁把这里的职责指引起类变化的原因,单一职责规定一个类有且只有一个引起它变化的原因,否则类应该被拆分。

这个原则提出是由罗伯特·C·马丁(Robert Cecil Martin)在他的《敏捷软件开发,原则,模式和实践》一书中,一篇名为〈面向对象设计原则〉的文章中给出。马丁表述该原则是基于《结构化分析和系统规格》一书中的内聚原则(Cohesion)上。

该原则提出了一个类不应该承担太多职责。如果一个类承担太多职责,那么类中一个职责的变化也可能引起其它职责的变化。承担太多职责也会导致类过于复杂,不利于程序变更和维护。

开闭原则(Open Closed Principle,OCP)

开闭原则(Open Closed Principle,OCP):软件实体应该对扩展开放,对修改关闭。

这个原则是说当应用的需求改变时,优先通过扩展现有代码功能,使其满足需求。也即是说当增加或修改需求时,可以通过增加代码来满足需求的变化,而不是修改原来的代码满足需求变化。

实现方法的话,可以通过 “抽象约束、封装变化”,即是通过接口或抽象类来为软件实体定义一个相对稳定的抽象层,将相同的可变因素封装在相同的具体实现类中。因为抽象灵活适应强,进行合理的抽象,可以保持程序软件架构的稳定。把易变的程序部分,用继承扩展抽象的实现类来进行扩展,当需求变化时,从抽象来实现一个扩展功能就可以了。

里氏替换原则(Liskov Substitution Principle,LSP)

里氏替换原则(Liskov Substitution Principle,LSP):继承必须确保超类所拥有的性质在子类中仍然成立。

这个原则说明了使用继承的原则,反映了父类和子类的关系。子类可以扩展父类的功能,而不应该改变父类原有的功能。父类可以被子类替换。它也是实现开闭原则的重要方式之一。也是保证类扩展后不会给已有的程序系统引入新的错误。

具体实现方法的话,需求变化时,子类继承父类,在子类中添加新的方法应对需求变化,尽量不要重写父类中的方法。

依赖倒置原则(Dependence Inversion Principle,DIP)

依赖倒置原则(Dependence Inversion Principle,DIP):上层模块不应该依赖下层模块,两者应该依赖抽象;抽象不应该依赖细节,细节应该依赖抽象。

对上面这句话直接理解就是:面向接口(抽象)编程,不要面向实现编程。通过引入抽象来减少程序间依赖,降低模块与模块、程序与程序之间的耦合。这也是上面 “高内聚低耦合” 原则中低耦合实现的重要方式。

在程序设计中,细节往往易变多变(实际上是需求变化多端引起程序细节变化),而良好抽象则相对稳定。因此通过良好的抽象来进行程序设计,比以细节为基础来进行程序设计往往要稳定。当然这是一个辩证关系,对细节了解足够多,才能进行良好抽象。

具体到面向对象语言设计中,抽象指的就是接口或抽象类,细节则是具体的实现类。利用接口或抽象类来制定规范或契约,而不涉及具体操作细节,把实现细节的任务交给实现类来完成。

接口隔离原则(Interface Segregation Principle,ISP)

接口隔离原则(Interface Segregation Principle,ISP):一个类对另一个类的依赖应该建立在最小的接口上。另外的定义就是程序不应该被迫依赖它不需要的方法。

建立在最小接口上,那可以对接口进行拆分处理,把庞大的接口拆分成更小接口和更具体的接口,让类实现仅依赖它需要的接口。而不是建立一个庞大的接口供所有依赖它的类去使用。拆分时候也要遵循高内聚低耦合原则和单一职责原则。

具体实现方法,就是上面说的接口拆分尽量小,但也不要无限小还是要掌握好度。一个接口只服务于一个业务逻辑,只提供调用者需要的方法。遵循内聚性,尽量减少与外界交互。

迪米特法则(Law of Demeter,LoD)

迪米特法则(Law of Demeter,LoD)又叫最少知道原则,只与你直接的朋友谈,不要跟陌生人说话。它的含义就是如果两个软件实体能不直接通信,就不要相互调用,可以通过第三方来实现调用。这个与前面的 “低耦合” 又相关,就是降低类与类、模块与模块之间的耦合度。

迪米特法则就是降低类与类之间的耦合度,提高类的相对独立性,提高复用性。

合成复用原则(Composite Reuse Principle,CRP)

合成复用原则(Composite Reuse Principle,CRP),它又叫聚合/组合原则。在程序设计时,尽量使用组合/聚合关系来实现程序功能,其次才考虑使用继承关系来实现功能。

合成复用同里氏替换两者相辅相成,都是开闭原则的具体实现规范。

为什么建议先用组合,后用继承,继承的一些缺点:

  1. 子类与父类耦合高。子类与父类具有某种连接,父类的实现细节继承给了子类,它们之间就出现连接,就耦合了。
  2. 限制了复用的灵活性。从父类继承而来的实现是静态,编译时已经定义,在运行时不可能发生改变。

控制反转IoC/依赖注入DI

控制反转(Inversion of Control,IoC),这个原则也是 “高内聚低耦合” 中低耦合的一种实现。

在面向对象程序设计中,应用程序都是通过两个或更多类,通过彼此合作来实现业务逻辑,这使得每个对象都需要获取与其合作的对象(也就是它依赖的对象)的引用,如果获取这个对象是靠自身实现,那么代码耦合度将变高。

具体实现方式有:依赖注入DI和依赖查找。

依赖注入在 Spring 框架中使用广泛,依赖注入实现方式又有好多种:

  1. 基于接口。实现特定接口以供外部容器注入所依赖类型的对象。
  2. 基于 set 方法。
  3. 基于构造函数。
  4. 基于注解。

依赖查找的方式,比如将框架提供的方法集中放在某个文件中,使用时在进行调用。

依赖稳定原则

前面提高的依赖接口,依赖抽象,都是依赖稳定的原则。

软件系统的构建要依赖稳定、可靠、变化小的程序。

== just do it ==
本文转载于网络 如有侵权请联系删除

相关文章

  • C# 定时执行方法

    大家好,又见面了,我是你们的朋友全栈君。定时执行某个方法privatevoidbutton1_Click(objectsender,EventArgse) { System.Timers.Timertimer=newSystem.Timers.Timer(); timer.Enabled=true; timer.Interval=4000;//执行间隔时间,单位为毫秒 timer.Start(); timer.Elapsed+=newSystem.Timers.ElapsedEventHandler(Timer1_Elapsed); }复制privatevoidTimer1_Elapsed(objectsender,System.Timers.ElapsedEventArgse) { //得到intHour,intMinute,intSecond,是当前系统时间 intintHour=e.SignalTime.Hour; intintMinute=e.SignalTime.Minute; intintSecond=e.SignalTime.Second; //System.Windo

  • 0d1n对Web应用程序的自动化定制渗透实验

    0d1n0d1n是一款针对Web应用程序的自动化定制渗透工具,该工具完全采用C语言开发,并且使用了pthreads线程库以实现更好的性能。在0d1n的帮助下,广大研究人员可以轻松对目标Web应用程序执行自动化定制渗透测试。工具功能以认证模式暴力破解登录凭证(账号和密码); 目录泄露(使用PATH列表进行爆破,并查找HTTP状态码); 测试以查找SQL注入漏洞和XSS漏洞; 测试以查找SSRF漏洞; 测试以查找命令注入漏洞; 支持为每一个请求加载反CSRF令牌; 支持对每一个请求设置随机代理; 更多功能即将上线…工具下载&安装该工具的正常运行要求libcurl-dev或libcurl-devel(基于RPMLinux的操作系统)。广大研究人员可以使用下列命令将该项目源码克隆至本地:$gitclonehttps://github.com/CoolerVoid/0d1n/复制接下来,使用下列命令安装和配置libcurl:$sudoapt-getinstalllibcurl-dev ortrylibcurl4-dev...libcurl* ifrpmdistro $sudoyumins

  • Android实现图片选择上传功能实例

    效果图:添加依赖:选择图片:compile‘com.lzy.widget:imagepicker:0.5.4’github地址:https://github.com/jeasonlzy/ImagePicker上传文件:compile‘com.zhy:okhttputils:2.6.2’github地址:https://github.com/hongyangAndroid/okhttputilsMainActivity.javapackagecom.yechaoa.uploadimage; importandroid.content.Intent; importandroid.support.v7.app.AppCompatActivity; importandroid.os.Bundle; importandroid.support.v7.widget.GridLayoutManager; importandroid.support.v7.widget.RecyclerView; importandroid.view.View; importandroid.widget.Adapter

  • Excel公式技巧21: 统计至少在一列中满足条件的行数

    在这篇文章中,探讨一种计算在至少一列中满足规定条件的行数的解决方案,示例工作表如下图1所示,其中详细列出了各个国家在不同年份废镍的出口水平。图1假设我们希望确定2004年出口总额大于或等于1000的国家的数量,可以使用公式:=COUNTIF(B2:B14,">=1000")或者:=SUMPRODUCT(N(B2:B14>=1000))如果希望计算2004年和2005年有多少个国家的出口总额大于或等于1000,可以使用公式:=COUNTIFS(B2:B14,">=1000",C2:C14,">=1000")或者:=SUMPRODUCT(N(B2:B14>=1000),N(C2:C14>=1000))现在,如果我们希望计算2004年和2005年的数据中至少有一个满足此标准的国家数量呢?由于数据较少,我们可以从工作表中清楚地标出满足条件的数据,如下图2所示。图2显然,“标准的”COUNTIF(S)公式结构不能满足要求,因为我们必须确保不要重复计数。实际上,在这种情况下,大多数人倾向于使用SUMPR

  • java核心技术第二篇之数据库SQL语法

    #查询products表记录 SELECT*FROMproductsWHEREprice>2000; –单行注释 /* 多行注释 */ #创建数据库 CREATEDATABASEhei66_day19_db;hei66_day19_db #查看数据库 SHOWDATABASES; #查看某个数据库的定义信息 SHOWCREATEDATABASEhei66_day19_db; #删除数据库 DROPDATABASEhei66_day19_db;#切换数据库 USEday21_267; SELECT*FROMproducts; #查看当前工作的数据库 SELECTDATABASE(); #创建学员信息表: CREATETABLEstudent( stuNoINT, stuName VARCHAR(200), stuSex CHAR(5), stuAge INT ); #查看数据库中有哪些表: SHOWTABLES;#查看表结构: DESCaccount;#删除表 DROPTABLEstudent;#为student表添加一个address列 ALTERTABLEstudentADDa

  • Octave使用plot错误

    问题在macos10.10.5上的Octave使用Plot时,出现如下错误:plot错误解决方案修改环境 每次在使用plot前输入:setenv("GNUTERM","qt")复制修改配置 在根目录下的.octaverc文件中加入setenv("GNUTERM","qt")vi~/.octaverc ****** setenv("GNUTERM","qt")复制重新安装GNU 如果上面配置仍然有问题的话,octave自带的gnuplot不行,需要重新安装gnuplotbrewuninstallgnuplot brewinstallgnuplot--with-x复制

  • Mac电脑使用虚拟机玩Win游戏,解决虚拟机游戏登录限制

    使用虚拟机玩Win游戏经常碰到被制裁的问题,也就是被检测到是虚拟机,不允许登录的问题(主要是游戏商家防止玩家双开)。DNF登录如下图:image.png既然不允许虚拟机运行,为什么我还去折腾?因为我不是要双开,就是单纯的想用Mac电脑玩玩游戏,我觉得这没什么不好的影响。那么在此声明:我后面的教程主要是为Mac使用者解决忧虑,不提倡破坏游戏平衡。 虚拟机我采用的是VMwareFusion也建议大家使用,千万别使用VirtualBox!!!我这样的强烈建议,你应该能从中窥视到它把我坑多很,不是说这个虚拟机软件不好,而是,如果玩游戏用它是不行了,如果你也碰到了启动游戏图组建设失败,那就是绘图3D加速没启动,那么久果断个模拟器吧。虚拟机安装,Tools(这个就是开启3D加速的插件)安装推荐这篇文章。我为什么写这篇博客?因为我被网上一些呆逼折磨了太久,我为什么这样说,我想使用Mac装Win虚拟机的都能明白我的感受...如千万头草泥马心中崩腾而过。 首先,我们来百度一下虚拟机解决限制登录问题,看看这些呆逼气人的地方.....image.pngMac哪来的记事本!!!这些人都不带脑子回答啊。我想大多

  • java实现多种排序算法

    冒泡排序/** *Createdbyjunyi.pcon2017/1/25. */ importjava.util.Calendar; importjava.util.Scanner; importjava.util.Vector; publicclassMain{ publicstaticvoidmain(String[]args){ inta[]={1,4,5,2,8,4,0,3}; intlen=a.length; for(inti=0;i<len-1;i++){ for(intj=len-1;j>i;j--){ if(a[j]<a[j-1]){ inttemp=a[j-1]; a[j-1]=a[j]; a[j]=temp; } } } for(inti=0;i<len;i++) System.out.print(a[i]+""); } } 或者这样效率低的更好记 /** *Createdbyjunyi.pcon2017/1/25. */ importjava.util.Calendar; importjava.util.Scann

  • 人工智能学习资料及其介绍

    [TOC]推荐学习微软人工智能公开课:https://docs.microsoft.com/zh-cn/learn0x00人工智能基础概念人工智能不是即将实现,而是已经实现了。 ArtificialIntelligenceAI使我们能够生成可以改进卫生保健的出色软件,让人能够克服生理上的不便,改进智能基础结构,创造令人惊叹的娱乐体验,甚至拯救地球!什么是AI?简而言之,AI即模仿人类行为和能力创建软件。关键要素包括:机器学习-它通常是AI系统的基础,也是我们“教”计算机模型进行预测并根据数据得出结论的方式。 异常情况检测-自动检测系统中的错误或异常活动的能力。 计算机视觉-软件通过相机、视频和图像直观地解释世界的能力。 自然语言处理-计算机理解书面或口头语言并作出相应反应的能力。 对话式AI-软件“代理”参与对话的能力。复制现在,人工智能可以帮助我们满足当下的需求,为明天做好准备。 我们可以用Microsoft的人工智能对当地的日光、风、雨进行预测。 在保护脆弱的环境的同时最大程度提高粮食产量方面,可持续农耕技术至关重要。TheYield是一家设在澳大利亚的农业技术公司,该公司使用

  • 腾讯云对象存储提交直播审核任务api接口

    功能描述本接口用于提交一个直播流审核任务。直播流审核功能为异步任务方式,您可以通过提交直播流审核任务审核您的直播流,然后通过查询直播流审核任务接口查询审核结果。 该接口支持情况如下: 说明: 支持审核视频直播,例如娱乐直播、线上授课等场景。 支持审核语音直播,例如语音聊天房、在线会议等场景。 支持对直播流进行自动检测,从OCR文本识别、物体检测(实体、广告台标、二维码等)、图像识别及音频审核四个维度,通过深度学习技术,识别直播流中的违规内容。 支持设置回调地址Callback获取检测结果,或通过查询直播审核任务结果主动轮询获取审核结果详情。 支持识别多种违规场景,包括:色情、违法、广告等场景。 支持根据不同的业务场景配置自定义的审核策略。 支持用户自定义配置风险库,打击自定义违规内容。 费用说明直播流的审核分为直播画面审核、直播声音审核,其中: 直播画面审核:通过直播流截帧将直播流截取为多张图片进行审核。 直播声音审核:将直播流声音分离出来进行音频审核。 每个审核场景单独计费,例如您选择审核涉黄、广告两种场景,则审核1个直播流,计2次审核费用。 调用接口会产生直

  • 腾讯云资源编排TIC查询资源栈列表

    1.接口描述接口请求域名:tic.tencentcloudapi.com。 本接口(DescribeStacks)用于查询一个或多个资源栈的详细信息。 可以根据资源栈ID来查询感兴趣的资源栈信息 若参数为空,返回当前用户一定数量(Limit所指定的数量,默认为20)的资源栈 默认接口请求频率限制:20次/秒。 APIExplorer提供了在线调用、签名验证、SDK代码生成和快速检索接口等能力。您可查看每次调用的请求内容和返回结果以及自动生成SDK调用示例。 2.输入参数以下请求参数列表仅列出了接口请求参数和部分公共参数,完整公共参数列表见公共请求参数。 参数名称 必选 类型 描述 Action 是 String 公共参数,本接口取值:DescribeStacks。 Version 是 String 公共参数,本接口取值:2020-11-17。 Region 否 String 公共参数,本接口不需要传递此参数。 StackIds.N 否 ArrayofString 按照⼀个或者多个资源栈ID查询 Offset 否 Integer 偏移量

  • Dive into TensorFlow系列(2)- 解析TF核心抽象op算子

    本文作者:李杰 TF计算图从逻辑层来讲,由op与tensor构成。op是项点代表计算单元,tensor是边代表op之间流动的数据内容,两者配合以数据流图的形式来表达计算图。那么op对应的物理层实现是什么?TF中有哪些op,以及各自的适用场景是什么?op到底是如何运行的?接下来让我们一起探索和回答这些问题。 一、初识op 1.1op定义 op代表计算图中的节点,是tf.Operation对象,代表一个计算单元。用户在创建模型和训练代码时,会创建一系列op及其依赖关系,并将这些op和依赖添加到tf.Graph对象中(一般为默认图)。比如:tf.matmul()就是一个op,它有两个输入tensor和一个输出tensor。 1.2op分类 op的分类一般有多个视角,比如按是否内置划分、按工作类型划分。 按是否内置划分,一般分为:内置op和自定义op(见“二、自定义op”部分介绍)。 按工作类型划分,一般分为:常见数学op、数组op、矩阵op、有状态op、神经网络op、检查点op、队列与同步op、控制流op。TF白皮书对内置op的分类总结如下:   1.3op与kernel o

  • Android Studio 之 ViewModel (转)

    ViewModel 是JetPack 类库中的一个功能,可以保存控件的状态,在整个Activity 生命周期中,状态不会失效 如屏幕翻转时,状态可保留,不会失效! 与LiveData 配合使用! 配合Room进行Sqlite 操作数据库       新建ViewModel 类,在MainActivity类的父结点上右击,点创建java类 注意:Superclass 中要选ViewModel     1.ViewModel 类中放一个public 的整数变量     2. 在MainActivity类中创建一个MyViewModel 实例, 注意:ViewModelProviders 这个对象,需要在build.gradle中的 dependencies结点中,添加引用  implementation'androidx.lifecycle:lifecycle-ext

  • 编写合格的C代码(1):通过编译选项将特定警告视为错误

    目录快速设定向错误的执念开炮,向C编译器开炮编译警告应当被忽略吗?warning不重要吗?(1)编库时调用了未定义函数(非编译器内置函数),编译只报warning;链接该库时报error(2)编库时调用了未定义函数(编译器内置同名函数),编译只报warning;链接该库时报error(3)编可执行时.c代码中使用了未定义的函数(编译器内置同名函数)(4)编可执行时.c代码中使用了未定义的函数(编译器无内置同名函数)个人总结的应当视作error的warning1.函数没有声明就使用2.函数虽然有声明,但是声明不完整,没有写出返回值类型。3.指针类型不兼容4.函数应该有返回值但是没有return返回值5.使用了影子变量(shadowvariable)6.函数返回局部变量的地址7.变量没有初始化就使用8.printf等语句中的格式串和实参类型不匹配9.把unsignedint和int类型的两个变量比较10.把int指针和int相互赋值在开发环境中配置上述CFLAGSTODO实录参考 快速设定 如果你没兴趣/没时间看具体解释、只想快速排错,请明确:这里列出了个人认为应当当作error但被C编译

  • 查看APK方法数的工具dex-method-counts

    做APK方法总能遇到方法数超限的问题(主要是方法数,字段数,String数。等各种数都可能超过65k导致不能安装) 除了大公司都自己做了一些检查方法。网上还有一些开源的查询工具。给大家推荐一个github: https://github.com/mihaip/dex-method-counts   下载完代码后,先按照要求处理一下才能使用: 如果使用ant的方式。   1.到下载后的目录,执行antjar    2.然后就可以执行 ./dex-method-countsxx.apk就出来结果了。

  • Call to undefined function imagecreatefromjpeg() 让GD支持JPEG格式的图片扩展

      安装扩展支持jpeg格式:     第一步:首先下载文件: 版本v8: wgethttp://www.ijg.org/files/jpegsrc.v8b.tar.gz 版本v9: wgethttp://www.ijg.org/files/jpegsrc.v9c.tar.gz 把jpeg安装到home目录:复制   复制 ./configure--prefix=/home/jpeg--enable-shared--enable-static make&&makeinstall 第二步:安装到配置文件中 1、找到php源码目录 cd/home/ubuntu/downphp/php-7.0.0 2、进入ext/gd目录 cd/home/ubuntu/downphp/php-7.0.0/ext/gd 3、执行命令:/home/php/bin/phpize [root@daokrgd]#/home/php/bin/phpize Configuringfor: PHPApiVersion:20151012 ZendModul

  • UEditor之斜线表头表格的定制

    效果图: 图1: 图2:  

  • Promise 的应用

    Promise 有三种状态,进行中(pending),已成功(fulfilled),已失败(rejected); 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。 Promise对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。 所以可以先实例化一个Promise对象,然后在使用then 方法为Promise对象添加成功或错误的回调函数,但一般只会添加成功的回调函数。然后用catch捕获错误执行错误的回调函数 1constfs=require("fs"); 2constpath=require("path"); 3

  • 我的书单mybooklist

    首先自我介绍一下,我是一名程序员。计算机的世界太浩瀚,而我太过渺小。比计算机的世界更为广大的是,书籍的海洋。学海无涯。无论是计算机的世界,还是其他类书的世界,人一辈子要看的书看也看不完。于是我常想知道,要是有值得信赖的人给我推荐一份书单,我也不至于在时间里茫然不知所措。而把自己的书单分享出去,照亮更多的人,真是一件很有意义的事情。于是我申请了域名www.mybooklist.cn,买了服务器。编写代码,想架构一个可以分享书单的网站。而与此同时,在世界的某个地方www.mybooklist.com的站长也做了同样的事情,我觉得我们真是有缘。比起搭建网站,制作有价值的书单,却是一件更加艰难的事情,因为首先要看书,然后才能分享出去,而我看的书实在有限。但我想,我们每个人坚持看书,把自己看过的书单分享出去,这样总比一个人做效率高。梦想总是要有的,万一实现了呢。

  • 快速排序实现及其pivot的选取

    coursera上斯坦福的算法专项在讲到快速排序时,称其为最优雅的算法之一。快速排序确实是一种比较有效的排序算法,很多类库中也都采用了这种排序算法,其最坏时间复杂度为$O(n^2)$,平均时间复杂度为$O(nlogn)$,且其不需要额外的存储空间。 基本步骤 快速排序主要使用了分治的思想,通过选取一个pivot,将一个数组划分为两个子数组。其步骤为:1.从数组中选择一个元素作为pivot2.重新排列数组,小于pivot的在pivot的左边,大于pivot的在其右边。3.递归地对划分后的左右两部分重复上述步骤。 简单的伪代码如下: 其中最主要的就是partition划分过程了。 划分过程 partition过程需要首先选择一个pivot,然后将小于pivot的元素放到左半部分,大于pivot的放到右半部分,并且最终pivot的位置及为其在排序好的数组中的最终位置。 这里使用第一个元素作为pivot,若选择其他元素作为pivot,则将其交换到第一个元素,这样可以保证代码的一致性及容易实现。示意图如下: 这里使用i和j,i和j最初为p+1的位置,在遍历的过程中i始终指向>p的第一

  • Spark重点难点知识总结

     转自: https://blog.csdn.net/shuhaojie/article/details/74205393 https://blog.csdn.net/shuhaojie/article/details/75123953   本博客是个人在学习Spark过程中的一些总结,方便个人日后查阅,同时里面出现的一些关键字也可以作为后来一些读者学习的材料。若有问题,欢迎评论,一定知无不言。   1.Tuple:Tuple就是用来把几个数据放在一起的比较方便的方式,注意是“几个数据”,因此没有Tuple1这一说。 valscores=Array(Tuple2(1,100),Tuple2(2,90),Tuple2(3,100),Tuple2(2,90),Tuple2(3,100)) valcontent=sc.parallelize(scores) valdata=content.countByKey() 执行结果 data:scala.collection.Map[Int,Long]=Map(1->1,3->2,2->2)

相关推荐

推荐阅读