程序=数据结构+算法。
数据结构是一种描述数据元素之间的关系的。
元素之间一对一的关系叫线性结构
元素之间一对多的关系叫树
元素之间多对多的关系叫图
在开发程序,设计算法,需要选择一种合适的数据结构。
1. 需要了解 常见数据结构及特性
2.选择 合适的数据结构和算法
3.分析出算法的时间复杂度和空间复杂度
需要一种抽象能力。
在写程序之前,必须要做的一步是分析:分析 待处理对象的特性 及对象之间的关系。
1. 抽象一个数据模型(分析问题,提取出操作对象,找出对象之间的关系(数据结构),用数学语言加以描述)
2.设计算法
3.编程、测试等
数据:比如 图片、声音等都是数据 (java中的所有对象,都是数据)
数据元素:组成数据的基本单位(java中具体的一个对象),一个数据元素可能包含若干数据项(对象中的 属性)
可以把数据元素看成一个对象,数据项就是对象的成员变量。
数据结构:数据元素存在的某种关系,这种关系成为结构,数据元素之间的关系就叫数据结构。
包括:线性结构、树结构、图结构
结构:
数组 是一种 地址连续的结构,如果使用 数组 来 表示数据结构的话, 元素可以不用包含 结构相关的 属性。
链表 是一种 跟地址存储无关的一种 表示 元素结构的方式。 使用 链表,需要在对象 内部 持有 表示 对象 关系的 属性。 比如: 线性关系,则需要持有 前驱 或者 后继指针; 树形关系 则需要 持有 父节点 、左子树、右子树 的指针,等等
数据结构的表示:
1. 数据的逻辑结构可以表示为:
一个二元组:(D,S)
D 数据(包含很多的数据元素)
S 数据元素存在的关系(逻辑上的关系)
这种定义的数据结构是对研究对象抽象出来的一种的学模型。
2. 数据结构在计算机中的表示:
叫做数据的物理结构或者存储结构:包括对数据元素的表示和元素之间关系的表示
2.1)计算机中表示数据:用若干位 二进制位 表示
2.2)计算机中表示关系:顺序存储、链式存储 两种
顺序存储:使用相对位置来表示元素之间的逻辑关系
链式存储:使用指针来表示元素之间的逻辑关系
算法的设计取决于数据结构
算法的实现取决于存储结构
抽象数据类型: 一个数学模型 和 定义在该模型上的一组操作。
抽象数据类型可以表示为一个 三元组
(D,S,P)
D:数据
S:关系
P:基本操作
ADT抽象数据类型名字{
数据:(数据对象的定义)
关系:(数据关系的定义)
基本操作:(数据操作的定义)
}
基本操作的定义:
基本操作名(参数表){
初始条件:(初始条件描述)
操作结果:(操作结果描述)
}
算法
一个算法由: 控制结构(顺序、分支、循环3种) 和 原操作(数据类型自己的操作) 构成。
时间复杂度:一般一个for循环是O(n),嵌套是O(n2),三层for循环是O(n3)
数据结构分类:
1. 线性表
2. 栈
3. 队列
4.树
5.图
哈希表
1. 哈希函数
确定 关键字 与 存储位置 对应关系的一种函数。
通过这个哈希函数,就可以明确的得的 关键字 的 存储位置。
存储位置可以称为哈希地址
2.哈希冲突
不同的关键字 通过哈希函数 得的了 相同的存储位置
在构造哈希表时:既要设定好一个 好的哈希函数,又要设定一种处理哈希冲突的方法
树
二叉树
结构约束
满二叉树
结构约束
完全二叉树
结构约束
二叉查找树
节点约束
平衡二叉树(AVL树)
树高度约束
平衡二叉树(红黑树)
节点类型约束
AVL 和 红黑树
平衡二叉树 | 平衡度 | 旋转频率 | 适用场景 |
AVL | 严格平衡 | 高 | 查询多,更新少 |
红黑树 | 弱平衡 | 低 | 更新多 |
AVL:
一般用平衡因子判断是否平衡并通过旋转来实现平衡,左右子树树高不超过1,和红黑树相比,AVL树是高度平衡的二叉树,平衡条件必须满足(所有节点的左右子树高度差不超过1)。不管我们是执行插入还是删除操作,只要不满足上面的条件,就要通过旋转来保持平衡,而的由于旋转比较耗时,由此我们可以知道AVL树适合用于插入与删除次数比较少,但查找多的情况,由于维护这种高度平衡所付出的代价比从中获得的效率收益还大,故而实际的应用不多,更多的地方是用追求局部而不是非常严格整体平衡的红黑树
红黑树:
也是一种平衡二叉树,但每个节点有一个存储位表示节点的颜色,可以是红或黑。通过对任何一条从根到叶子的路径上各个节点着色的方式的限制,红黑树确保没有一条路径会比其它路径长出两倍,因此,红黑树是一种弱平衡二叉树(由于是弱平衡,可以看到,在相同的节点情况下,AVL树的高度<=红黑树),相对于要求严格的AVL树来说,它的旋转次数少,所以对于搜索,插入,删除操作较多的情况下,用红黑树
总结:
自平衡的二叉树,维护平衡需要进行 旋转操作,这部分操作 相对来说比较耗时,因此,数据量大的情况下,维护起来 性能不高。AVL 和 红黑树 都是一种自平衡的二叉树。而 AVL树,是高度平衡的,因此每次都可能需要进行旋转。红黑树 是弱平衡的,降低了 维护次数,提高了整体性能。
以上主要是针对内存数据,磁盘数据存储需要用多叉树。
传统用来搜索的平衡二叉树有很多,如 AVL 树,红黑树等。这些树在一般情况下查询性能非常好,但当数据非常大的时候它们就无能为力了。原因当数据量非常大时,内存不够用,大部分数据只能存放在磁盘上,只有需要的数据才加载到内存中。一般而言内存访问的时间约为 50 ns,而磁盘在 10 ms 左右。速度相差了近 5 个数量级,磁盘读取时间远远超过了数据在内存中比较的时间。这说明程序大部分时间会阻塞在磁盘 IO 上。那么我们如何提高程序性能?减少磁盘 IO 次数,像 AVL 树,红黑树这类平衡二叉树从设计上无法“迎合”磁盘
索引的效率依赖与磁盘 IO 的次数,快速索引需要有效的减少磁盘 IO 次数,如何快速索引呢?索引的原理其实是不断的缩小查找范围,就如我们平时用字典查单词一样,先找首字母缩小范围,再第二个字母等等。平衡二叉树是每次将范围分割为两个区间。为了更快,B-树每次将范围分割为多个区间,区间越多,定位数据越快越精确。那么如果节点为区间范围,每个节点就较大了。所以新建节点时,直接申请页大小的空间(磁盘存储单位是按 block 分的,一般为 512 Byte。磁盘 IO 一次读取若干个 block,我们称为一页,具体大小和操作系统有关,一般为 4 k,8 k或 16 k),计算机内存分配是按页对齐的,这样就实现了一个节点只需要一次 IO
B树/B-tree
每个节点可以有 多个子节点
索引值和数据 都 存储 在节点中
B+树
非叶节点 只用来索引,不保存 数据
叶子节点保存 元素的全部信息,节节点之间 顺序、双向链表进行组织
B树和B+树:
1)范围查询
B+树可以找到范围下限,然后通过叶子节点的链表顺序遍历即可。
B 树,只能通过中序遍历查找
总结:
B树 和 B+树 都是 针对 磁盘存储的。因为 磁盘I/O性能 比较差,为了 减少I/O次数,使用每个节点存储多个数据域,并且每个节点可以有多个子节点的方式,来减少磁盘I/O次数,提高查询性能。
但是,B树的 节点 存储 元素的所有信息,B+树 只是页节点存储元素所有信息,非叶节点只存储索引信息,这样可以更好的减少磁盘I/O