演示网站: [数据结构演示](Red/Black Tree Visualization (usfca.edu))
数组是我们使用到的最简单的一个数据结构,数组的使用
1,数组
//动态初始化:初始化时由程序员只指定数组长度,由系统为数组元素分配初始值
char c1[] = new char [5];
//静态初始化:初始化时由程序员显示置项每个数组的初始值,由系统决定数组长度
char c2[] = new char []{'E', 'D' ,'U' , 'Y','U'};
char c3[] = {E', 'D', 'U','Y','U'};
具有如下的特点:
- 内存地址连续, 查询效率高, 增删效率低
- 可以通过下标的成员访问,下标访问的性能高
- 增删操作带来更大的性能消耗(保证数据越界的问题,需动态扩容)
- 扩容只能重新创建一个数组, 并把原数组的元素转移过去
- 删除一个元素, 需要把后面的元素挪到前面去
2,链表
链表也是线性的顺序存储数据。只是在内存地址上不是连续的,每一个节点里存到下一个节点的指针(Pointer)
1.2.1单向链表
查找效率低, 增删效率高
单向链表(单链表)是链表的一种,它由节点组成,每个节点都包含下一个节点的指针,下图就是一个单链表,表头为空,表头的后继节点是"结点10"(数据为10的结点),“节点10"的后继结点是"节点20"(数据为10的结点)
然后我们来看下删除链表的操作,比如删除30这个节点,只需要把20指向40即可
填加元素操作, 只需把20指向30, 30再指向40即可
1.2.2 双向链表
双向链表(双链表)是链表的一种。和单链表一样,双链表也是由节点组成,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双肉链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
双链表的示意图如下:
双向链表具体实现参考
public class Node{
//前一个节点
volatile Node prev;
//后一个节点
volatile Node next;
//链表节点存储的具体数据
volatile Object obj;
}
我们看看双向链表删除节点的操作,比如说下面这个单链表中我们要删除"节点30"。
删除之前:“节点20"的后继节点为“节点30",“节点30"的前继节点为“节点20"。“节点30"的后继节点为"节点40",“节点40"的前继节点为”节点30”。
删除之后:“节点20"的后继节点为"节点40",“节点40"的前继节点为“节点20"。
我们再来看看双向链表添加节点的操作,比如说下面这个双向链表在“节点10"与"节点20"之间添加"节点15"
添加之前:“节点10"的后继节点为"节点20",“节点20"的前继节点为"节点10"。
添加之后:“节点10"的后继节点为"节点15",“节点15”的前继节点为"节点10”。“节点15"的后继节点为“节点20",“节点20"的前继节点为"节点15"。
3, 二叉树
3.1相关概念
**二叉树:**每个子节点只有两个节点的树,每个结点至多拥有两棵子树(即二叉树中不存在度大于2的结点),并且,二叉树的子树有左右之分,其次序不能任意颠倒。
二叉查找树也称为有序二叉查找树,满足二叉查找树的一般性质,是指一棵空树具有如下性质:
- 任意节点左子树不为空,则左了树的值均小于根节点的值
- 任意节点右子树不为空,则右子树的值均大于于根节点的值
- 任意节点的左右子树也分别是二叉查找树
- 没有键值相等的节点 , 值不能重复
二叉树又分为: 完美二叉树, 完全二叉树, 完满二叉树
完美二叉树: 又称为满二叉树, 除了叶子节点之外的每一个节点都有两个孩子节点, 每层都被完全填充
完全二叉树: 除了最后一层之外的其他每一层都被完全填充,并且所有的节点都保持向左对齐
完满二叉树: 除了叶子节点之外的每一个节点都有两个孩子节点。
3.2 遍历操作
二叉树中的遍历规则有如下三种:
**中序遍历: **所谓的中序遍历就是先访问左节点,再访问根节点,最后访问右节点,即左-根-右遍历
先序遍历: 所谓的前序遍历就是先访问根节点,再访问左节点,最后访问右节点,即根-左-右遍历(前序)
后序遍历: 所谓的后序遍历就是先访问左节点,再访问右节点,最后访问根节点。即左-右-根遍历
查找最小值: 沿着根节点的左子树一路查找,直到最后一个不为空的节点,该节点就是当前这个树的最小节点
查找最大值: 沿着根节点的右子树一路查找,直到最后一个不为空的节点,该节点就是当前这个树的最大节点
查找前驱节点: 小于当前节点的最大值 4的前驱是3
查找后继节点: 大于当前节点的最小值 4的后驱是5
3.3 删除节点
二叉树中的删除节点:本质上是找前驱节点或者后继节点来替代
- 叶子节点直接删除
- 只有一个子节点的用子节点替代(本质上就是找的前驱节点或者后继节点,左节点就是前驱节点右节点就是后继节点)
- 有两个子节点的,需要找到替代节点(替代节点就是前驱节点或者后继节点)
3.4 查找局限性
一个二叉查找树是由n个节点随机构成,所以,对于某些情况,二叉查找树会退化成一个有n个节点的线性链.如下图