笔记 编程综合

编程语言概念

是什么:计算机语言01——高级语言——更接近人类思维,更容易看懂的语言

分类:

  • 静态 vs 动态 编程语言:在静态类型语言(statically typed languages)中,类型检查发生在编译阶段(compile time),因此所有的变量类型必须被显示地声明,因为这些信息在编译阶段就被需要,且不可以在运行时改变变量的类型。然而,在动态类型语言(dynamically typed languages)中,类型检查发生在运行阶段(run time),因此显示声明不被要求,类型赋值发生在运行阶段,可以在运行时改变变量的类型。

  • 强类型 vs 弱类型 编程语言:强类型语言中,一旦某一个变量被定义类型,如果不经过强制转换,则它永远就是该数据类型了,它会持有这个类型,并且不能同其他类型在计算某个表达式时混合计算,例如 Python。然而,在弱类型中,可以对变量的类型做隐式转换,可以与其他类型混合计算,比如同样一门伟大的语言 Javascript。(语言的强弱类型暂存争议

怎么学:

横向:语言——类库——框架(把类库以最佳方案组合好,避免自己组装出错)

纵向:命令行,桌面程序,设备程序,web程序 ……

代码规范

参考:读《代码不朽:编写可维护软件的10大要则》C# 版

可维护性

质量好的软件类和类库的依赖关系清晰,好维护。

可维护性是软件质量的一个标准,代表一个系统可被修改的难易程度。所以它是面向程序员的,假设两个软件完成相同的功能,但一个软件的源码,让其他人或者一段时间之后的自己,很难理解,更不用提修改了,就说明这个软件的可维护性比另一个差。

软件维护的4种方式:

  • 发现并纠正bug(纠正性维护

  • 适应操作系统或运行环境的改变(适应性维护

  • 根据需求增加新的功能(完善性维护

  • 改进代码质量预防bug产生(预防性维护

编写可维护软件的10大编程原则:

  • 编写短小的代码单元

  • 一个巨型的方法会包含很多细节,很难有一模一样的场景使用这个方法;小的方法容易理解,容易重用和进行单元测试

  • 超过15行的方法就可以考虑拆分

  • 编写简单的代码单元

    • 限制每个代码单元分支点的数量不超过4个。C# 中常见的分支点代码就是if和switch语句

    • 简单的代码更容易修改和测试,分支点过多,意味着要有更多的测试用例

    • 如何写简单:根据情况分析,一般会提取方法、引入新数据结构、修改语句等

  • 不写重复代码

    • 重复代码指一段多行相同或者逻辑相同的代码

    • 重复代码出现在不同的地方,不利于源码的定位;如果需要修改的地方正是重复的代码,意味着要做很多重复性的工作,而且容易出错

    • 可以把重复的代码拆分

  • 保持代码单元的接口简单

    • 限制每个代码单元的参数不能超过4个,较少的接口参数能够保持简单的上下文,易于重用、理解和修改

    • 可以使用“使用方法对象替换方法”的重构技巧,将多个参数包装成对象,比如输入坐标参数,x与y可以包装成一个点对象

  • 分离模块之间的关注点

    • 模块对应类的概念,就是要求类要保持小的体积,不要过大过复杂

    • 小的体积的类带来了类之间的松耦合,松耦合意味着类能更灵活的适应将来的变化。如果一个类做了很多事情,其耦合度会越来越紧,积攒大量代码,导致代码很难阅读和修改

    • 分离方法:1可以根据功能将大类拆分为小类;2提取一个接口,实现松耦合;3使用第三方库和框架来替代自定义的实现

  • 架构组件松耦合

    • 组件是比模块(类)更高一层的单元,设计到系统的架构。此原则要求尽可能减少当前模块暴露给(例如,被调用)其它组件中模块的相关代码

    • 独立的组件可以单独进行维护,方便划分职责,让测试变得容易

    • 如何松耦合:使用抽象工厂设计模式,简单的讲就是类的实例不能直接被创建(new一个),而是通过工厂类的方法返回。这种通用的工厂接口背后,隐藏了具体产品的创建过程。在这个环境下,产品通常都不止有一种类型。如果要使用其中的逻辑,需要通过创建通用的工厂对象调用类方法成员。(ps. 抽象工厂不同于工厂模式,简单理解就是抽象工厂的类型不止一个,所以产品至少有两个。

  • 保持架构组件之间的平衡

    • 保持源代码中的组件数量接近于9

    • 好的组件平衡让查找和分析代码更容易,提供清晰的功能边界,分离维护职责

    • 保持方法:1基于功能领域划分的系统,好处是可以从高层功能的角度来分析代码,坏处是技术人员需要了解多个技术栈;2基于技术划分的系统,根据技术专长来划分,可能会有前端,后端,接口、日志等组件

  • 保持小规模代码库

    • 大型系统更加难以维护,易出现更密集的缺陷,以大型代码库为目标的项目更容易失败

    • 如何保持小规模:1功能层面:控制需求蔓延,功能标准化;2技术层面:不要复制黏贴代码,重构代码,使用第三方库和框架(前面提到过)

  • 自动化开发部署和测试

    • 测试包含单元测试、集成测试、端对端测试、回归测试、验收测试。

    • 不同类型的测试需要不同的自动化框架

  • 编写简洁的代码

  • 编写单元级别的良好代码

  • 不要编写不好的注释

  • 不要注释代码

  • 不要保留废弃代码(比如注释代码、不可能执行到的代码、无用的私有方法、注释中的代码

  • 不要使用过长的标识符名称

  • 不要使用魔术常量(指表达式中突兀出现的数字,应该先定义。

  • 不要使用未正确处理的异常(包括以下情况:捕获异常却不处理(catch为空),直接捕获通用异常(比如Exception异常,这些异常不会提供触发失败的状态或事件信息,所以没意义),将异常信息展示给终端用户(避免用户困惑或暴露信息,应该先转换为通用信息)

操作系统

概念

用户与计算机硬件之间的接口,控制和管理计算机资源的软件。参考

程序:程序(program)是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象,一个操作系统可以执行的文件。举个例子:QQ.exe

进程(process)程序的一次执行,包含代码与数据;是资源分配的基本单位。

程序的一次执行过程,或是正在运行的一个程序。是一个动态的过程,有它自身的产生、存在和消亡的过程(生命周期)。进程作为资源分配的基本单位,系统在运行时会为每个进程分配不同的内存区域。举个例子:同时挂三个 QQ 号,它们就对应三个 QQ 进程,退出一个就会杀死一个对应的进程

线程(thread)进程的一个执行单元;调度和执行的基本单位,比进程更小的独立运行的单位;

进程可进一步细化为线程,是一个程序内部的一条执行路径。若一个进程同一时间并行执行多个线程,就是支持多线程的。线程作为调度和执行的基本单位,每个线程拥有独立的运行栈和程序计数器(pc),线程切换的开销小。一个进程中的多个线程共享相同的内存单元/内存地址空间,它们从同一堆中分配对象,可以访问相同的变量和对象。这就使得线程间通信更简便、高效。但多个线程操作共享的系统资源可能就会带来安全的隐患

线程切换:多核CPU能更好的发挥多线程的效率,单核CPU是一种假的多线程,因为在一个时间单元内,也只能执行一个线程的任务。

CPU:计算单元ALU 寄存器组Registers 指令存储器PC

并行:多个CPU同时执行多个任务。 并发:一个CPU(采用时间片)同时执行多个任务

核心:进程和线程的管理

计算机硬件组成:CPU,存储器,输入/输出设备,总线等

进程

一个程序有且只有一个进程,进程是正在运行的程序的实例,而线程是进程中的实际运作单位,一个进程可以有多个线程

进程拥有独立的地址空间,不同进程之间互不相关,而线程没有。一个进程崩溃不会对其他进程造成影响;不同线程共同拥有相同进程的地址空间,一旦一个线程崩溃,整个进程就会崩溃

线程不占用系统资源,调度线程比进程开销更小,在线程间切换效率更高,线程间可以并发,可以共享进程数据,有自己独立的栈空间和执行序列

线程好处:线程间通信无需调用内核即可实现,同一进程的线程共享进程的数据

内核:是一个操作系统的核心。是基于硬件的第一层软件扩充,提供操作系统的最基本的功能,是操作系统工作的基础

进程通信:消息传递  消息队列  管道  共享内存  套接字socket

多线程

多线程(multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程,进而提升整体处理性能。
在一个程序中,这些独立运行的程序片段叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理”。参考

Socket

TCP/IP协议族:应用层(用户进程) socket抽象层 传输层(TCP UDP) 网络层(IP ICMP) 链路层(媒体接口 ARP RARP)

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口,把复杂的TCP/IP协议族隐藏在Socket接口后面,用户只需要使用一组简单的接口,其余交给Socket,

服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。如果有客户端也初始化了一个Socket,然后连接服务器(connect),然后如果连接成功,客户端与服务器端的连接就建立了。

客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

socket()打开文件,bind()函数,listen()监听、connect()发出连接请求,accept()服务器端接收请求,read()、write()函数,close()函数

socket中TCP的三次握手:

客户端调用connect时,触发了连接请求,向服务器发送了SYN J包,这时connect进入阻塞状态;

服务器监听到连接请求,即收到SYN J包,Socket  Listen都被动打开,调用accept函数接收请求向客户端发送SYN K ,ACK J+1,这时accept进入阻塞状态;

客户端收到服务器的SYN K ,ACK J+1之后,connect返回,并对SYN K进行确认;

服务器收到ACK K+1时,accept返回,连接TCP建立。是一方主动打开,另一方被动打开的。

socket中TCP的四次挥手:

TCP连接释放。客户端想要释放连接,向服务器端发送一段TCP报文,其中,标记位为FIN,表示请求释放连接,进入半关闭状态;

服务器端接收到,发送,标记位为ACK,表示“接收到客户端发送的请求”,进入半关闭状态,开始准备释放连接;

服务器端做好准备后,发送报文,标记位为FIN,ACK,表示“已经准备好释放连接了”;

客户端发送,标记位为ACK,表示“接收到服务器准备好释放连接的信号”,然后客户端等待两毫秒,如果在两毫秒内收到服务端的FIN报文,就再发一遍。

确认号syn seq Ack 保证了TCP报文传输的连贯性。

OSI七层

“互联网的本质就是一系列的网络协议(OSI协议)。”

OSI(开放式系统互连),不同层间功能有重复:物理层,数据链路层,网络层,传输层,会话层,表示层,应用层。

应用层:为应用程序提供服务,规定应用程序中通信方面的细节;规定应用程序的数据格式(超文本传输http/安全超文本https协议)。

表示层:主要负责数据格式的转换,jpg txt等,用计算机的形式表示出来,编码解码加密解密;

会话层:负责建立和断开两个应用间的通信连接,比如qq和csdn可,微信和淘宝不可;

传输层:对其上三层提供传输服务,对网络层提供可靠的目的地站点信息主要功能;端口间通信(TCP/UDP协议),给数据打上端口号,提供端到端的交换数据的机制;套接字(socket);(数据段

        TCP是可靠传输,传输效率低,只能点对点,可以传文件。首先TCP是一种面向有链接的协议,首先经过三次握手建立连接,只有在确认通信对端存在时才会发送数据;

        UDP是不可靠传输,适用于对可靠性要求不高,数据量小的传输,比如QQ聊天。

网络层:跨网络传输(IP协议):路由+转发(交给网关)。给数据包ip地址(在哪个局域网),路由器据此和路由表来转发,主要负责寻找地址和路由选择,还有检错纠错,流量控制,拥塞控制等功能(数据包

        路由器:连接各个网段,把数据包送到对的网段;

数据链路层:局域网内部传输(物理地址寻址)+数据分组成帧+差错控制CRC检验+流量控制+重发。含网卡mac地址(在局域网的哪个位置);负责物理层面上的互联的、节点间的通信传输;(

        协议:ARP、RARP、PPP、帧中继等

       交换机:记录MAC和IP的对应关系,把数据包送到对的收件人;

物理层:定义标准,规定了通信端点之间的机械特性(水晶头的引脚,接口形状)、电气特性(电压范围,距离限制)、功能特性(高电平代表什么意思);为上层协议提供传输数据的物理媒体(bit)

最终:以太网首部14+IP首部20+TCP首部20+(应用数据)+以太网尾部4bit

四层

物理层  网络层IP  传输层TCPUDP  应用层HTTP;

IP协议:用IP地址来标识Internet的主机:IP数据报中,有源IP地址和目标IP地址,IP数据报传输时,每个中间节点(IP 网关)会为其选择转发路径(路由表)。IP协议可以根据路由选择协议提供的路由信息对IP数据报进行转发,直至抵达目的主机(路由表,下一跳,掩码)

        ARP协议:IP地址和MAC地址的匹配。数据链路层使用MAC地址来发送数据帧,因此在实际发送IP报文时,还需要进行IP地址和MAC地址的匹配,由TCP/IP协议簇中的ARP(地址解析协议)完成。

TCP协议:IP协议是找到对方的详细地址,TCP协议就是把信息可靠的传输,UDP是不可靠的传输,TCP属于传输层,提供可靠的字节流服务(信息切割,拆解运输,确保安全性)大块数据分割成以报文段为单位的数据包

超文本传输HTTP协议:应用广泛的网络通信协议,可以发布和接收Web服务器上的html页面;浏览器向服务器发送请求,而服务器回应相应的网页,是个标准的客户端——服务器模型;

        HTTP只能客户端发起请求,服务器端响应,因此也限制了服务端无法在客户端没有请求的前提下,自行推送消息给客户端。

数据结构

数据结构是相互之间存在一种或多种特定关系的数据元素的集合

包含: 逻辑结构 物理结构(存储结构)

逻辑结构: 集合结构,同属于一个集合,之间没有其他关系 线性结构,一对一的关系 树形结构,一对多的层次关系 网状结构,多对多

物理结构: 顺序,物理连续;非顺序,可以离散;

        顺序存储 数据间的逻辑关系与物理关系一致

        链式存储 索引存储在存储元素信息的同时,还建立附加的索引表,表中的每项称为索引项,索引项的一般形式是(关键字,地址)

        散列/哈希存储 根据元素的关键字直接计算出该元素的存储地址

数据类型

数据: 描述客观事物的符号,能被计算机识别并输入给计算机的符号集合

数据元素: 是组成数据且有一定意义的基本单位,在计算机中一般作为整体处理。也被称为记录

数据项: 一个数据元素可以由若干个数据项组成,数据项不可分割,是数据的最小单位

数组:创建一个数组时,数组名其实就是一个指针,指向数组的第一个元素

数组在一段连续的内存上存储,在创建数组时,需要指定数组的容量大小,先为其分配内存。

数组名其实就是一个指针,指向数组的第一个元素

c++的stl库中的动态数组vector,先开一个小空间,空间容量不够的话,就重新分配一块原来空间2倍的空间,然后将数据转移到新数组中,再将之前的数组内存释放。对时间性能有负面影响,所以动态数组要尽量少改变容量大小的次数

字符串:C/C++中每个字符串都是以‘\0’结束,String对象一旦被创建就是固定了,后续JVM字符串常量池不收一模一样的字符串,对它的任何改变都不影响到原对象,如果使用change会生成新的对象

由于String字符串的不可变性,我们可以十分肯定字符串常量池中一定不存在两个相同的字符串

链表:动态数据结构,空间效率比数组高

树:根节点没有父节点,其它有唯一父节点,叶节点无子节点,其它有一或多子节点

栈:系统为每个线程一般都会创建一个栈用来存放函数调用时候都各个函数的参数、返回地址和临时变量等

队列:层序遍历树的时候,可以利用队列的结构,用来存放每一层的子节点,然后下一层依次遍历子节点;也可用于广度优先遍历

排序

稳定排序:直接插入 冒泡排序 归并排序 基数排序

不稳定排序:希尔排序 快速排序 选择排序 堆排序

线性排序:基数排序

线性对数阶:快排 堆排 归并排序

平方阶:直接插入 直接排序 冒泡排序

希尔:增量序列8421

选择:给每个位置选择当前元素最小的

直插:每轮把一个数放在前面的有序数组里

直接:最开始用的

拓扑排序:是一个有向无环图的所有顶点的线性序列(对于同一个有向图而言可能存在多个这样的结点排序)

必须满足,1每个顶点出现且只出现一次,2若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面

排序类似流程图一样;作用是如果表示一个工程,其中每个顶点表示工程中的一个任务,用有向边表示在做任务 B 之前必须先完成任务 A,故在这个工程中,任意两个任务要么具有确定的先后关系,要么是没有关系,绝对不存在互相矛盾的关系

方法是:1初始化,将所有入度边数为 0 的点放入 stack 栈中(储存 入度边个数为 0 的点)

2每次删除一个入度边个数为 0 的点,并刷新其他点的出度边个数(遍历 A 点的出度边并删除)

3直到不存在入读为0的点

查找TODO

顺序查找:无序表

二分查找:mid=(low+high)/2,先与中间结点的关键字比较,中间结点把表分成两个子表,若相等则查找成功;若不相等,再与该中间结点比较结果确定下一步查找哪个子表,然后递归进行,直到查找到或查找结束

哈希表:"直接定址"与"解决冲突"是哈希表的两大特点,用给定的哈希函数构造哈希表根据选择的冲突处理方法解决地址冲突,如拉链法和线性探测法,以空间换时间

分块查找:索引顺序查找,顺序查找的一种改进方法;

插值查找:二分进化,mid=low+((value-low)/(high-low))*(high-low),时间复杂度O(log2(log2n))

二叉树:若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值。中序遍历即可得到有序的数列;可用于构建哈夫曼编码;

B树:2-3树的一种扩展,他允许一个节点有多于2个的元素

(树// TODO)

最短路径算法:深度、广度优先搜索算法、弗洛伊德算法、迪杰斯特算法

迪杰斯特拉算法:解决单源最短路径

所有的顶点分为两部分,已知最短路径的顶点集合P和未知的Q,初始状态时,集合P中只包含源点。

在集合Q中选择一个离源点距离最小点加入到P中。并以它为新的中心点,对每一条边进行松弛操作(更新各顶点到起点的距离)。

不断重复,直到集合Q中的顶点全部加入到集合P中.

弗洛伊德:解决多源最短路径

时间复杂度O(n^3),空间复杂度O(n^2),算法思路源于动态规划,故核心为该表达式:map[i][j] = min(map[i][j], map[i][k]+map[k][j])。

最开始只允许经过1号顶点进行中转,接下来只允许经过1号和2号顶点进行中转......允许经过1~n号所有顶点进行中转,来不断动态更新任意两点之间的最短路程

最小生成树:保证整个拓扑图的所有路径之和最小,但不能保证任意两点之间是最短路径

普里姆算法Prim:

从任意一个结点开始,将结点分成两类:已加入的,未加入的。

每次从未加入的结点中,找一个与已加入的结点之间边权最小值最小的结点。然后将这个结点加入,并连上那条边权最小的边。

重复n-1次。

克鲁斯卡尔算法kruskal:

将无向图中相互连通的一些点称为处于同一个连通块中。

首先将所有的边按从小到大顺序排序(一般使用快排),并认为每一个点都是孤立的,分属于n个独立的集合。

然后按顺序枚举每一条边。如果这条边连接着两个不同的集合,那么就把这条边加入最小生成树,这两个不同的集合就合并成了一个集合;如果这条边连接的两个点属于同一集合,就跳过。

直到选取了n-1条边为止。

常见算法

动态规划

核心思想:利用历史记录,来避免重复计算。历史记录一般是用数组来保存。缺点是空间复杂度较高。

  1. 定义数组的元素含义
  2. 找出数组元素之间的关系式,有一点类似于高中的归纳法,当我们要用前n-1位来推出第n位的,也就是利用历史数据来推出新的元素值,所以我们要找出数组元素之间的关系式,例如 dp[n] = dp[n-1] + dp[n-2]。
  3. 找出初始值

通常用于解决具有重叠子问题和最优子结构性质的问题,如取小球(每次1or2个)、走格子(只能向下或向右移动)、背包问题、计算图的最短路径、计算字符串的最长公共子串、斐波那契额数列(F(n)=F(n - 1)+F(n - 2))等。

单调栈

单调递增栈:只有比栈顶元素小的元素才能直接进栈,否则从栈顶开始遍历栈中元素,把小于 x 或者等于 x 的元素弹出栈,直到遇到一个大于 x 的元素为止,然后再把 x 压入栈中。

这样就保证了:栈中保留的都是比当前入栈元素大的值,并且从栈顶到栈底的元素值是单调递增的。

使用场景:寻找右侧第一个比当前元素大的元素。

贪心

自顶向下求解,只能选择眼前对自己最有利的一步,其他的路径看不见,因此有时会找不到真正的最优解。

使用场景:找零钱问题、背包问题、最小生成树问题、一些单调性问题等。

// 已知一个无向图,其边有权值,求解一个最小生成树,即含有所有顶点的连通子图并且权值最小
// 贪心:从任一顶点开始,每次选择一条权值最小且不会构成回路的边

分治法TODO

设计模式

可分为:创建型、结构型和行为型3大类 参考参考2参考3

创建型模式

对象实例化的模式,创建型模式用于解耦对象的实例化过程。

可以为适合的状况提供相应的对象创建方法。因为对象的创建会消耗掉系统的很多资源,所以单独对对象的创建进行研究,从而能够高效地创建对象就是创建型模式要探讨的问题。

  • 工厂模式:
  • 简单工厂模式:建立一个实例化对象的类,在该类中对多个对象实例化。
  • 实际使用案例:1.通过工厂类创建工厂; 2.通过工厂和对象类型“梁”调用具体产品类创建梁;
  • 抽象工厂模式:抽象产品、具体产品、抽象工厂、具体工厂。定义了一个接口用于创建对象族,而无需明确指定具体类。抽象工厂也是把对象的实例化交给了子类,即支持拓展。同时提供给客户端接口,避免了用户直接操作子类工厂。
  • 围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂,可以用来生产不同产品族的全部产品。参考
  • 实例:
    抽象接口类实现类
    构件:1.墩柱项目1
    项目2
    2.梁项目1
    项目2
    工厂:1.生成墩柱 2.生成梁项目1(墩,梁)
    项目2(墩,梁)
    工厂生成器类
  • 实际使用案例:1.通过工厂生成器类和工厂类型创建具体的实例工厂; 2.通过实例工厂和对象类型得到具体的产品实例;3.使用;4.释放,因为是new的对象*p,动态分配在堆里的,所以需要手动delete然后把对象指针置为NULL;

  • 产品族:一个品牌下面的所有产品;例如华为下面的手机,路由器,电脑 称为华为的产品族;

  • 建造者模式【Builder】:将一个复杂对象的构建过程与其表示相分离,从而可以创建具有不同表示形式的对象。
  • 建造者模式的结构需要产品(Product需要构建的产品对象)、抽象建造者(Builder)、具体建造者(ConcreteBuilder)、指挥者(Director)四个角色。
  • 产品(Product):表明需要构建的产品对象,内含产品变量
  • 抽象建造者(Builder):定义创建对象所需的步骤以及创建的步骤的调用过程
  • 具体建造者(ConcreteBuilder):可能有多个,对于不同的创建过程可以用不同的类实现
  • 指挥者(Director):使用 Builder 的类,提供给调用方使用,调用方通过使用指挥者来获取产品
  • 原型模式【Prototype】:用于创建重复的对象,同时又能保证性能。使用了clone方法。
  • 深拷贝和浅拷贝:深复制进行了完全彻底的复制,而浅复制不彻底,其引用类型指向的还是原对象所指向的。clone明显是深复制,clone出来的复制体是是不能去影响原型对象的。
  • 单例模式【Singleton】:有实例返回实例,没有实例自己创建自己的唯一实例,并提供一个全局访问点给所有其他对象提供这一实例。
  • 减少内存开销,避免资源的多重占用(如写文件操作);但是与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心实例化方式。
  • 分为两种:预加载和懒加载。懒加载不浪费内存,但是无法保证线程的安全。

结构型模式

通常用来处理实体之间的关系,把类或对象结合在一起形成一个更大的结构。

在解决了对象的创建问题之后,对象的组成以及对象之间的依赖关系就成了开发人员的关注焦点,因为如何设计对象的结构、继承和依赖关系会影响程序的维护性、代码的健壮性、耦合性等。

  • 外观模式【Facade】:对外提供一个统一的方法,来访问子系统中的一群接口。
  • 适配器模式【Adapter】:将一个类的方法接口转换成客户希望的另一个接口,对不同的接口进行适配,从而便于版本的兼容性以及其他功能。
  • 代理模式【Proxy】:为其它对象提供一个代理以便控制这个对象的访问。
  • 装饰模式【Decorator】:动态的给对象添加新的功能。
  • 桥接模式【Bridge】:将抽象部分和它的实现部分分离,让双方可以独立的变化。
  • 组合模式【Composite】:将对象组合成树形结构以表示“部分-整体”的层次结构。
  • 享元模式【Flyweight】:通过共享技术来有效的支持大量细粒度的对象。

行为型模式

用于在不同的实体间进行通信,类和对象如何划分责任和通信、交互。

在对象的创建和对象的结构问题都解决了之后,就剩下对象的行为问题了。如果对象的行为设计的好,那么对象的行为就会更清晰,它们之间的协作效率就会提高。

  • 访问者模式【Visitor】:不改变数据结构的前提下,增加作用于一组对象元素的新功能。
  • 模板方法模式【Template Method】:使用模板面向抽象编程,便于新的子类的实现和管理
  • 策略模式【Strategy】:定义一系列算法,把他们封装起来,并且使它们可以相互替换。
  • 状态模式【State】:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
  • 状态模式将一个状态看做一个类,这与以往我们对类的理解不一样。我们通常认为对象是具体的事物,类是对对象的抽象,而现在我们将状态这种非具体的看不见的但又真实存在的事物作为类描述的东西,然后通过控制状态的逻辑委托不同的状态去做不同的事情。
  • 观察者模式【Observer】:发布订阅模式。对象间的一对多的依赖关系。
  • 当被观察者的状态发生改变的时候会主动通知观察者,将自己的状态传递过去,
  • 备忘录模式【Memento】:在不破坏封装的前提下,保持对象的内部状态。
  • 把某一时刻的状态保存下来,便于恢复,在游戏中使用的比较多。
  • 调停/中介/仲裁者模式【Mediator】:用一个中介对象来封装一系列的对象交互。
  • 当控件的状态发生改变的时候会向仲裁者发出信息,让仲裁者进行仲裁,用来解除复杂对象之间的相互调用的关系
  • 迭代器模式【Iterator】:一种遍历访问聚合对象中各个元素的方法,不暴露该对象的内部结构。
  • 解释器模式【Interpreter】:给定一个语言,定义它的文法的一种表示,并定义一个解释器。
  • 命令模式【Command】:将命令请求封装为一个对象,使得可以用不同的请求来进行参数化。
  • 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。这意味着创建一个类,包含实现该操作所需要的所有逻辑和方法。
  • 职责/责任链模式【Chain of Responsibility】:

设计模式六大原则:

  • 单一原则:1.对于一个类,只有一个引起该类变化的原因;2.该类的职责是唯一的,且这个职责是唯一会引起其他类变化的原因。
  • 接口隔离原则:客户端不应该依赖它不需要的接口,一个类对另一个类的依赖应该建立在最小的接口上。
  • 建立单一接口(类也是一种接口,一切皆接口)。
  • 依赖倒置原则:面向接口编程。
  • 细节依赖于抽象而抽象不依赖于细节,程序依赖于抽象接口而不依赖于具体实现。
  • 开闭原则:对扩展开放,对修改关闭(Open for extension, closed for modification)
  • 用抽象构建架构,用实现扩展原则;这意味着模块通过扩展来实现变化,而不必修改原来的代码。
  • 迪米特原则:又叫做最少知道原则。
  • 就是说一个对象应当对其它对象有尽可能少的了解,尽量少的相互作用,降低类与类之间的耦合。
  • 里氏替换原则:子类可以扩展父类的功能,但不能改变原有父类的功能;任何基类可以出现的地方,子类一定可以出现。
  • 里氏代换原则是继承复用的基石,只有当衍生类可以替换基类,软件单位的功能不受影响时,基类才能真正的被复用,而衍生类也能够在基类的基础上增加新的行为。
  • 里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
  • 合成复用原则:要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。如果要使用继承关系,则必须严格遵循里氏替换原则。
  • 合成复用原则同里氏替换原则相辅相成的,两者都是开闭原则的具体实现规范。

计算机组成原理

计算机组成原理总复习——知识点总结_中二病没有蛀牙的博客-CSDN博客

计算机五大组成:运算、控制、存储、输入输出

硬件协议——缓存一致性协议,具体与硬件有关,软件层面无法控制,可能带来效率损失

分布式——缓存一致性协议,是指在分布式系统中,多个节点之间共享一个缓存时,保证缓存中的数据一致性的协议。常见的缓存一致性协议包括:基于锁的协议,基于版本号的协议,基于时钟的协议

数据表示、运算:二进制计算、原反补码

控制器部件

存储器系统

主存、Cache、辅存、虚存,CPU多核多线程

高速缓存Cache

CPU为何要有高速缓存:

根据摩尔定律,CPU每18个月翻一番。

内存和硬盘的发展速度远远不及CPU,然而CPU的高度运算需要高速的数据,因此在CPU中内置了少量的高速缓存以解决I\O速度和CPU运算速度之间的不匹配问题。

带有Cache的CPU执行计算的流程:

  • 程序以及数据被加载到主内存Memory

  • 指令和数据被加载到CPU的高速缓存Cache

  • CPU执行指令,把结果写到Cache

  • Cache中的数据写回Memory

CPU访问存储设备原理:在CPU访问存储设备时,无论是存取数据抑或存取指令,都趋于聚集在一片连续的区域中,被称为局部性原理

  • 时间局部性(Temporal Locality):如果一个信息项正在被访问,那么在近期它很可能还会被再次访问。

  • 空间局部性(Spatial Locality):如果一个存储器的位置被引用,那么将来他附近的位置也会被引用。

三级缓存 L1L2L3

文件TODO

总线:数据、地址、控制

接口:功能、标准

输入输出

指令、指令系统

分布式TODO

计算机网络TODO

计算机网络和互联网

七层

五层

网络安全

无线和移动网络

多媒体网络

网络管理

ping

BIOS:Basic Input Output System,基本输入输出系统;计算机在运行时,首先会进入BIOS

ICMP:Internet Control Message Protocol,因特网控制消息协议;它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。

ICMP协议在实际传输中数据包:20字节IP首部 + 8字节ICMP首部 + 1472字节<数据大小>38字节。

ICMP报文格式:IP首部(20字节) + 8位类型 + 8位代码 + 16校验和 + (不同类型和代码,格式也有所不同)。

ping:Packet Internet Groper,因特网包探索器;用于测试网络连接量的程序;Ping发送一个数据(使用的是ICMP协议);回声请求消息给目的地并报告是否收到所希望的ICMP echo (ICMP回声应答)。它是用来检查网络是否通畅或者网络连接速度的命令。

向指定的网络地址发送一定长度的数据包,按照约定,若指定网络地址存在的话,会返回同样大小的数据包,当然,若在特定时间内没有返回,就是“超时”,会被认为指定的网络地址不存在。

Ping 127.0.0.1:检查本地的TCP/IP协议有没有设置好;

Ping本机IP地址:检查本机的IP地址是否设置有误;

Ping远程IP地址:ping www.baidu.com,检查本网或本机与外部的连接是否正常;

网页获取流程

控制

1.DNS解析(Domain Name System Resolution)

浏览器首先将输入的网址发送给DNS服务器,以获取网址对应的IP地址。DNS服务器将网址解析为对应的IP地址。

2.TCP连接(Transmission Control Protocol)

浏览器使用获取到的IP地址与Web服务器建立TCP连接。TCP连接确保数据的可靠传输。

3.发送HTTP请求

一旦TCP连接建立成功,浏览器会向Web服务器发送HTTP请求。HTTP请求包含了请求的类型(GET、POST等)、路径、头部信息以及其他参数。

4.服务器处理请求

Web服务器接收到浏览器发送的HTTP请求后,根据请求的内容进行处理。服务器可能会读取文件、查询数据库或执行其他操作来生成需要的网页内容。

5.服务器发送响应

Web服务器生成响应内容,并以HTTP响应的形式发送回浏览器。响应包含了响应的状态码(例如200表示成功、404表示页面未找到等)、头部信息以及响应的内容

6.接收响应

浏览器接收到服务器发送的HTTP响应后,开始接收响应的内容。响应的内容通常是HTML、CSS、JavaScript等文件。

7.解析文档

浏览器对接收到的HTML文档进行解析,构建DOM(Document Object Model)树,这是由HTML标记构成的树形结构,表示网页的结构和内容。

8.加载资源

浏览器解析HTML文档时,如果遇到外部资源(例如CSS、JavaScript、图像等),会发送额外的HTTP请求来获取这些资源。

9.渲染页面

浏览器根据构建好的DOM树和CSS样式信息,将网页内容渲染到用户的屏幕上。这包括布局、绘制文本、应用样式等过程。

10.执行JavaScript

如果HTML文档中包含JavaScript代码,浏览器会执行这些代码,以添加交互性和动态效果到页面上。

11.加载完成

当所有资源都加载完成,页面渲染完毕后,网页加载过程就完成了。

以下是一个简单的代码演示,展示了网页加载的过程:请注意,这只是一个简化的示例代码,实际的实现可能会更加复杂,并涉及到更多的细节和处理。

const url = 'https://example.com'; // 输入的网址// DNS解析
const ipAddress = dnsLookup(url);// 建立TCP连接
const socket = establishTCPConnection(ipAddress);// 发送HTTP请求
const httpRequest = createHTTPRequest(url);
socket.send(httpRequest);// 接收响应
const httpResponse = socket.receive();// 解析文档
const domTree = parseHTML(httpResponse);// 加载资源
const resourceURLs = extractResourceURLs(domTree);
for (const resourceURL of resourceURLs) 
{  
    const resourceRequest = createHTTPRequest(resourceURL);  
    socket.send(resourceRequest);  
    const resourceResponse = socket.receive();  
    cacheResource(resourceURL, resource response);  
}// 渲染页面
renderPage(domTree);// 执行
JavaScriptexecuteJavaScript(domTree);// 加载完成
console.log("页面加载完成");
function dnsLookup(url) {// 执行DNS解析逻辑// 返回解析得到的IP地址}
function establishTCPConnection(ipAddress) {// 建立TCP连接逻辑// 返回建立的Socket对象}
function createHTTPRequest(url) {// 创建HTTP请求逻辑// 返回HTTP请求对象}
function parseHTML(httpResponse) {// 解析HTML文档逻辑// 返回DOM树对象}
function extractResourceURLs(domTree) {// 提取资源URL逻辑// 返回资源URL列表}
function cacheResource(url, response) {// 缓存资源逻辑}
function renderPage(domTree) {// 渲染页面逻辑}
function executeJavaScript(domTree) {// 执行JavaScript逻辑}

其它

正则

正则表达式就是记录文本规则的代码,和通配符类似( *.doc,在这里,**会被解释成任意的字符串)

入门:

  • hi:查找前一个字符是h,后一个是i的字符串,包含hi这两个连续的字符,比如him, history, high

  • \bhi\b:精确地查找hi这个单词(元字符\b,代表单词的分界处)

  • \bhi\b.*\bLucy\b:hi后面任意个任意字符(但不能是换行),然后跟着一个Lucy(元字符. ,匹配除了换行符以外的任意字符)(限定符*,代表数量——它指定自己前边的内容可以重复任意次)(.*相连就意味着任意数量的不包含换行的字符)

  • \bhi\b.+\bLucy\b:hi后面任意个任意字符(但不能是零个)(限定符+,代表数量——重复一次或多次)(限定符?,代表数量——重复一次或零次)(限定符{n},代表数量——重复n次)(限定符{n,},代表数量——重复n次或更多次)(限定符{n,m},代表数量——重复n到m次)

  • 0\d\d-\d\d\d\d\d\d\d\d:以0开头,然后是两个数字,然后是一个连字号“-”,最后是8个数字(也就是中国的电话号码)(元字符\d,匹配一位数字)(“-”不是元字符,只匹配它本身)

    • 0\d{2}-\d{8}:也可以这样写这个表达式

  • (\s匹配任意的空白符,包括空格,制表符,换行符,中文全角空格等)

  • \ba\w*\b:以字母a开头的单词(元字符\w,匹配字母或数字或下划线或汉字等)

  • \b\w{6}\b:刚好6个字符的单词

  • ^\d{5,12}$:5位到12位数字(元字符^和$,都匹配一个位置,和\b有点类似。^匹配要查找的字符串的开头,$匹配结尾)

  • C:\\Windows:C:\Windows(转义字符\,如果查找元字符本身的话,可能会出现问题,可以使用\来取消这些字符的特殊意义)

  • ^\w+:一行或整个字符串的第一个单词

  • [a-z0-9A-Z_]:指定字母数字(元字符[],指定一个字符范围)

进阶:

  • 分支条件:

  • 分组:

  • 反义:

  • 后向引用:

shell命令

参考;(不全)

  • 文件操作命令:

  • ls:列出目录的内容
  • cd:改变目录
  • pwd:打印当前工作目录
  • cat:查看文件内容
  • 搜索命令:
  • find:在文件系统中搜索文件或目录。
  • 目录操作命令:

  • mkdir:创建一个新的目录
  • rmdir:删除一个空目录
  • df:显示磁盘使用空间
  • 权限操作命令:

  • chmod:更改文件或目录的权限
  • chown:更改文件或目录的所有者和所属的组
  • chgrp:更改文件或目录的所属组
  • 网络操作命令:

  • ping:发送网络请求以测试网络连接
  • ssh:远程登录或执行远程命令
  • 进程和系统控制命令:

  • ps:显示当前进程的状态
  • top:动态显示运行中的进程

  • kill:发送信号以终止进程

  • 文本操作命令:

  • echo:打印信息到终端。
  • printf:格式化并打印信息。
  • 压缩与解压命令:

  • tar:创建、展开及管理tar包。
  • zip/unzip:创建和解压zip格式的压缩包。
  • 磁盘使用管理命令:

  • df:报告文件系统磁盘空间使用情况。
  • 包管理命令:

  • 环境变量命令:

  • env:显示当前所有的环境变量。
  • set:显示当前shell所有的环境变量及函数。
  • export:设置或显示环境变量。
  • 系统信息发布命令:

  • uname:会打印操作系统的名称。hostname:打印系统的主机名
  • w:展示哪些用户正在登录。
  • 系统控制命令:

  • halt:关机。
  • reboot:重启系统。
  • passwd:更改用户密码。
  • 文本编辑命令:

  • 其他有用命令:

  • man:查看命令的帮助文档。

  • whatis:显示一个命令的简单描述。

  • whereis:查找命令的二进制文件、源文件及帮助文档位置。

  • whoami:打印当前有效的用户名。
  • date:显示或设置系统日期和时间

JSON

JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据,层次简洁清晰,易于人阅读和编写,同时也易于机器解析和生成,是理想的数据交换语言之一。

数据存储优势:

常用的存储数据的方式有很多,比如txt文件,xml,word,Excel,数据库等,各有优势。

相对于txt,word来说,json格式更加明确,获取重要信息非常方便。
相对于xml来说,json格式更加简洁,存储同样的文件,花费的内存更小。
相对于Excel来说,json更适合存储字符类文件。Excel相当于比较简单的数据库了。
相对于数据库来说,json更加方便,数据库我们还需要做一些设置,安装一些软件。json可以直接使用。

示例:这是一个简单的json文件:

{
   "age" : 99,
   "friends" : {
      "friend_age" : 88,
      "friend_name" : "mille",
      "friend_sex" : "woman"
   },
   "hobby" : ["eat", "sleep", "run"],
   "name" : "enna",
   "sex" : "man"
}

JSON读写(C++):

// 读json:
void readStrProJson()
{
	string strValue = "{\"name\":\"shuiyixin\",\"major\":[{\"AI\":\"MachineLearning\"},{\"AI\":\"DeepLearning\"},{\"AI\":\"ComputerVision\"}]}";
	Json::Reader reader;
	Json::Value value;
	if (reader.parse(strValue, value))
	{
		string out = value["name"].asString();
		cout << out << endl;
		const Json::Value arrayObj = value["major"];
		for (unsigned int i = 0; i < arrayObj.size(); i++)
		{
			out = arrayObj[i]["AI"].asString();
			cout << out<<endl;
		}
	}
}

// 写json:

参考

数据库

SQL(Structured Query Language)是“结构化查询语言”,它是对关系型数据库的操作语言,可以应用到所有关系型数据库中。

SQL 语句可以单行或多行书写,以分号结尾;可以用空格和缩进来来增强语句的可读性;关键字不区别大小写,建议使用大写;

如果列名称包含空格,要求使用双引号或方括号;

SQL 分类:DDL、DML、DCL、DQL。

DDL(Data Definition Language):数据定义语言,用来定义数据库对象:库、表、列等;

  • 操作数据库:
  • 查看所有数据库:show databases;
  • 切换数据库:use mydb1,切换到 mydb1 数据库;
  • 创建数据库:CREATE DATABASE [IF NOT EXISTS] mydb1;在名为 mydb1 的数据库不存在时创建该库,避免报错
  • 删除数据库:DROP DATABASE [IF EXISTS] mydb1;加上[IF EXISTS]后,就算 mydb1不存在,也不会报错
  • 修改数据库编码:ALTER DATABASE mydb1 CHARACTER SET utf8
  • 数据类型:
  • int, double, decimal泛型, char, varchar固定长度字符串, text, blob字节, date, time, timestamp时间戳
  • 操作表:
  • 创建表:CREATE TABLE 表名(列名 列类型,列名 列类型……);
  • 查看表结构:DESC 表名
  • 修改表名:ALTER TABLE 表名 RENAME TO 新表名;
  • 添加列:ALTER TABLE 表名 ADD (列名 列类型);
  • 修改列的数据类型:ALTER TABLE 表名 MODIFY 列名 新列类型;
  • 修改列名:ALTER TABLE 表名 change 列名 新列名 列类型;
  • 删除列:ALTER TABLE 表名 DROP 列名;

DML(Data Manipulation Language):数据操作语言,用来定义数据库记录(数据);

  • 插入数据:
  • INSERT INTO 表名(列名 1, 列名 2, …) ;
  • INSERT INTO 表名 VALUES(值 1, 值 2,…);
  • 修改数据:
  • UPDATE 表名 SET 列名 1=值 1, … 列名 n=值 n [WHERE 条件];
  • 删除数据:
  • DELETE FROM 表名 [WHERE 条件];
  • TRUNCATE TABLE 表名;
  • ——DELETE的效率没有 TRUNCATE 高。TRUNCATE 属于 DDL 语句,因为它是先 DROP TABLE,再 CREATE TABLE。但TRUNCATE删除的记录是无法回滚的,DELETE删除的记录是可以回滚的;

DCL(Data Control Language):数据控制语言,用来定义访问权限和安全级别

  • 创建用户:CREATE USER ‘用户名’@地址 IDENTIFIED BY '密码';
  • 给用户授权:GRANT 权限 1, … , 权限 n ON 数据库.* TO ‘用户名’@地址;
  • 撤销授权:REVOKE 权限 1, … , 权限 n ON 数据库.* FROM ‘用户名’@地址;
  • 查看用户权限:SHOW GRANTS FOR ‘用户名’@地址;
  • 删除用户:DROP USER ‘用户名’@地址;
  • 修改用户密码(以root身份):use mysql; alter user '用户名'@localhost identified by '新密码';

DQL(Data Query Language):数据查询语言,用来查询记录(数据)

  • select 列名 from 表名 where 行条件 group by 分组列 having 分组条件 order by 排序列 limit 起始行, 行数

  • 1基础查询:

  • 查询所有列:SELECT * FROM 表名;

  • 查询指定列:SELECT 列名 1, 列名 2, …列名 n FROM 表名;

  • 2条件查询:

  • 含有 WHERE 子句及关键字 =、!=、<>、<、<=、>、>=;BETWEEN…AND;IN(set);IS NULL;AND;OR;NOT

  • WHERE 是对分组前记录的条件,如果某行记录没有满足 WHERE 子句的条件,那
    么这行记录不会参加分组;而 HAVING 是对分组后数据的约束,一般在 GROUP BY 之后。

  • 3模糊查询:

  • SELECT 字段 FROM 表 WHERE 某字段 Like 条件; 条件:%表示任意 0 个或多个字符,_表示任意单个字符。

  • 4字段控制查询:

  • 去重:SELECT DISTINCT 列1 FROM 表1;

  • 加运算:SELECT *, 列1+列2 FROM 表1; 需要列1列2都是数值类型;

  • 别名:SELECT 列名 FROM 表名 AS 别名;SELECT 列名 AS 别名 FROM 表名;

  • 实例:SELECT w.name, w.url, a.count, a.date FROM Websites AS w, access_log AS a WHERE a.site_id=w.id and w.name="CSDN";

  • 5排序:

  • SELECT * FROM stu ORDER BY sage ASC;ASC升序,DESC降序,不写默认ASC;

  • 实例:SELECT * FROM 表 ORDER BY 列1 DESC ,列2 ASC; 按列1降序排序,如果列1相同,按列2升序排序

  • 6聚合函数:

  • COUNT():统计指定列不为 NULL 的记录行数;

  • MAX():计算指定列的最大值,如果指定列是字符串类型,那么使用字符串排序运算;

  • MIN():计算指定列的最小值,如果指定列是字符串类型,那么使用字符串排序运算;

  • SUM():计算指定列的数值和,如果指定列类型不是数值类型,那么计算结果为 0;

  • AVG():计算指定列的平均值,如果指定列类型不是数值类型,那么计算结果为 0;

  • 实例1,查询表中记录数:SELECT COUNT(*) AS 别名 FROM 表;

  • 实例2:查询表中列1不为空的记录数:SELECT COUNT(列1) AS 别名 FROM 表;

  • 实例3:查询表中列1不为空且列2不为空的记录数:SELECT COUNT(列1) , COUNT(列2)  FROM 表;

  • 实例4:查询表中列1+列2的数值和:SELECT SUM(列1+IFNULL(列2, 0)) FROM 表;

  • 实例5:查询列1平均值:SELECT AVG(列1) FROM 表; 或者:SELECT SUM(列1), COUNT(列1) FROM 表;

  • 7分组查询:

  • SELECT 列1, SUM(列2) FROM 表 GROUP BY 列1 HAVING SUM(列2) > 100;

  • 8LIMIT:

  • 用来限定查询结果的起始行,以及总行数。SELECT * FROM 表 LIMIT start, n;查询 n 行记录,起始行从 start 开始;
  • 9多表连接查询:
  • 内连接:仅选出两张表中互相匹配的记录。select 表1.列a, 列2_1 from 表1, 表2 where 表1.列a=表2.列a;
  • 外连接:分为左连接和右连接,会选出其他不匹配的记录。
  • 左连接:select 表1.列a, 列2_1 from 表1 left join 表2 on 表1.name=表2.name;

参考

加密

MD5算法:

MD5 用的是 哈希函数,它的典型应用是对一段信息产生 信息摘要,以 防止被篡改。严格来说,MD5 不是一种 加密算法 而是 摘要算法。无论是多长的输入,MD5 都会输出长度为 128bits 的一个串 (通常用 16 进制 表示为 32 个字符)。

很多网站在数据库存储用户的密码的时候都是存储用户密码的MD5值。这样就算不法分子得到数据库的用户密码的MD5值,也无法知道用户的密码。(比如在UNIX系统中就是以MD5(或其它类似的算法)经加密后存储在文件系统中。当用户登录的时候,系统把用户输入的密码计算成MD5值,然后再去和保存在文件系统中的MD5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。这不但可以避免用户的密码被具有系统管理员权限的用户知道,而且还在一定程度上增加了密码被破解的难度。

参考

RSA算法:

RSA 加密算法是目前最有影响力的 公钥加密算法,并且被普遍认为是目前 最优秀的公钥方案 之一。RSA 是第一个能同时用于 加密 和 数字签名 的算法,它能够 抵抗 到目前为止已知的 所有密码攻击,已被 ISO 推荐为公钥数据加密标准。

RSA 加密算法 基于一个十分简单的数论事实:将两个大 素数 相乘十分容易,但想要对其乘积进行 因式分解 却极其困难,因此可以将 乘积 公开作为 加密密钥。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值