红黑树
定义
定义:
- 红黑树的所有节点的颜色要么是红色的,要么是黑色的
- 红黑树中不能有连续两个红色节点
- 红黑树中从任意一个节点出发,到空叶节点经过的黑色节点数相同
- 红黑树的所有空叶节点(也就是外部节点)都是黑色的
- 红黑树的根节点是黑色的
插入
红黑树的插入:
按照BST的方法,找到对应位置插入,然后将这个节点涂成红色
7. 若这个节点是根节点,那么将这个节点颜色染黑即可
8. 若这个节点的父节点为黑色节点,不需要任何操作
9. 若这个节点的父节点为红色节点,叔叔节点为红色节点,那么将叔叔节点和父节点染成黑色,将爷爷节点染成红色,此时将爷爷节点看作是新插入的节点,递归处理
10. 父节点是红色,叔叔节点是黑色时:
(1) (父节点是左孩子,插入节点也是左孩子)或者(父节点是右孩子,插入节点也是右孩子): 将父节点和爷爷节点颜色互换,然后对爷爷节点进行一次左旋
(2) (父节点是右孩子,插入节点是左孩子)或者(父节点是左孩子,插入节点是右孩子):对父节点进行左旋,然后将父节点看做新插入的节点,递归处理
删除
注意外部节点(空叶节点)不算作是儿子节点
- 当删除节点有两个儿子时,不能直接对这个节点进行删除,需要先用这个点的直接前驱或者直接后继来填补这个点,然后转化为对直接前驱或直接后继的删除
- 若这个节点只有左子树或者只有右子树: 直接删除,同时子树替代自己的位置,并染黑色
- 当这个节点没有子树时:
(1).节点是红色时,直接删除
(2).节点是黑色,兄弟是红色时: 交换节点和父节点的颜色,同时对父节点做一次左旋,然后删除
c语言
27×10^15(天河速度)
C语言函数调用过程
为什么python不用声明变量而c中需要声明变量
c必须声明变量名而python不用声明变量名
python不用声明变量原因
函数调用函数调用栈
c语言函数调用
c函数调用
c函数调用(强烈推荐)
总的来说,函数调用的过程,首先存在栈顶指针Esp和每个函数栈帧开始的位置的寄存器ebp,每次调用新的函数时,首先把保存现场,把这条指令的下一条指令的地址eip压入栈中,然后给被调用的函数开辟一个新的栈帧,保存上一个函数的ebp,再让ebp保存这个函数的新栈帧的其实位置。
中断
P NP
项目
FLP定理:在网络可靠,但允许节点失效(即便只有一个)的最小化异步模型系统中,不存在一个可以解决一致性问题的确定性共识算法(不存在一个解决这个通用场景的确定的算法,需要根据不同的场景,有针对性的共识算法,也就是不同场景需要设计不同的共识算法)
分布式时钟同步:
- 例如信号量的同步
- 物理时钟(所有计算机使用一个物理时钟来定位时间,但是不同的计算机时间可能有所不同,因此可能导致差异)
- 逻辑时钟:逻辑时钟我们要求的不是像物理时钟上严格意义上的时间顺序,而是表示了事件发生的顺序,常见的逻辑时钟的方法有Lamport时钟同步
同步就是同步处理,一个事件必须在某个事件发生后进行
异步就是分时处理,一个事件不必在某个事件发生后执行
面向对象三大特性:封装,继承,多态
封装 (Encapsulation)是面向对象方法的重要原则,就是把对象的属性和操作(或服务)结合为一个独立的整体,并尽可能隐藏对象的内部实现细节。
继承 是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。
多态 是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的实例而执行不同操作,通俗来讲就是同一个行为,不同的类的对象来执行表现出不同的特征
多态
多态详解
虚函数和纯虚函数的区别
多态的实现建立在子类继承父类的基础上,它是由C++编译器的一个核心技术实现,即动态绑定技术。其核心思想是父类对象调用子类对象的方法。而父类对象调用子类对象的方法时,这个被调用的方法必须在父类中声明为虚函数,因此虚函数是实现多态的一个中介。而纯虚函数是将父类上升为一个抽象类,**抽象类无法实例化,只有方法的声明,其实现由其子类完成。**就像动物无法实例化为具体的对象,而老虎、狮子都可以继承动物的特性(即父类的接口),从而有自己的实例化对象。
虚函数和虚函数表
注释事项:
- 每个类声明的对象的这个对象的内存空间中都有一个虚函数表指针,这个指针指向这个类的虚函数表,这个类的虚函数表存在于全局数据区.data中,这个类的所有对象,共享这一个虚函数表,虚函数表中包含了这个类的所有虚函数的地址
- 从父类中继承过来的子类,会有自己单独的一片空间,存放自己的虚函数表,子类会首先把父类的虚函数表copy过来,然后再把虚函数表中的虚函数地址替换成自己的虚函数的地址
数据库
设计模式
面向对象设计原则
面向对象设计原则
开闭原则:对扩展开放,对修改关闭
里氏替换原则: 子类可以扩展父类的功能,但是不能替换父类的功能
迪米特原则: 降低类之间的耦合,每个类尽可能减少对其他类的依赖
单一职责原则: 让每一个类/接口有且仅有一个职责
接口分离原则: 不能强迫用户使用他们不使用的接口
依赖倒转原则: 高层模块不应依赖底层模块,要针对接口编程,不要针对实现编程
聚合复用原则:尽量使用组合,不要使用类继承
设计模式详解
设计模式总共分为三大类:
创建型模式,结构型模式,行为型模式
软件工程部分
绪论部分
软件定义
软件是在计算机支持下,能够完成特定功能的程序,数据和文档
其中,程序是能够被计算机所理解的语句序列
软件是一种逻辑产品
软件质量的一些判断标准:
正确性,有效性,可用性,可靠性,可维护性,可移植性,安全性
软件危机
软件危机:软甲开发和维护过程中遇到的一系列问题(比如:成本高,维护困难,移植困难等)
软件工程
IEEE对于软件工程的定义:把系统的、规范的、可度量的途径应用于软件开发、运行和维护过程,也就是把工程应用于软件
软件生命周期
瀑布模型
V模型
快速原型模型
迭代模型
螺旋模型
敏捷开发
敏捷开发的核心理念:就是既然我们无法充分了解用户的真实需求是怎样的,将一个大的目标不断拆解,把它变成一个个可交付的小目标,然后通过不断迭代,以小步快跑的方式持续开发
需求工程
软件设计
UML(统一建模语言 Unified modeling language)
软件概要设计主要设计用例图(明确我们开发的功能和模块),包图(明确各个模块之间的架构关系),时序图(明确各个模块之间运转的流程),状态图(各个模块之间交互关系)
软件详细设计主要是类图,时序图,状态图
需求视图
结构视图
类图
对象图
包图
行为视图
顺序图
状态图
活动图
软件测试部分
软件缺陷: 代码中的错误(静态的)
软件错误: 代码中的错误导致运行时,某个中间结果错误但是还没直观的被人们感知到
软件失效: 软件运行结果错误,被人们直观的感受到了
软件测试5个过程
动态测试
动态测试包括: 黑盒测试, 白盒测试
黑盒测试
模糊测试是黑盒测试中的随机测试的一种方法,常见的工具有: American Fuzz loop,更够构造大量的种子输入
白盒测试
语句覆盖: 语句覆盖要求设计足够的测试用例,使得程序中每条语句至少被执行一次。
分支覆盖: 分支覆盖,它要求设计足够多的测试用例,使得程序中每个判定至少有一次为真值,有一次为假值,即程序中的每个分支至少执行一次。每个判断的取真、取假至少执行一次。(每个分支的真假分支都要覆盖到)
条件覆盖: 条件覆盖要求设计足够多的测试用例,使得判定中的每个条件获得各种可能的结果,即每个条件至少有一次为真值,有一次为假值。(判定中的每个条件比如 a && b, 条件覆盖要求a和b都要各自取过真值和假值)
MC/DC(判定/条件覆盖): 设计足够多的测试用例,使得判定中每个条件的所有可能结果至少出现一次,每个判定本身所有可能结果也至少出现一次。
基本路径覆盖:设计足够的测试用例,覆盖程序中所有可能的路径。也就是说,使得程序的每条可能路径都至少执行一次。若流程图中有环,则每个环至少经过一次。
动态测试前沿
静态测试
规则检查
比如 clang-tidy 规则检查, 能够静态分析检查代码中的错误规则
比如
禁止使用goto语句
禁止局部变量和全局变量重名
禁止形参和类型名相同
禁止形参和标识符名相同