Java数据结构

60 阅读6分钟

数据结构

特点:后进先出,先进后出

队列

特点:先进先出,后进后出

数组

特点:查询快,增删慢

  • 查询速度快:查询数据通过地址值和索引定位,查询任意数据耗时相同。(元素在内存中是连续存储的)
  • 删除效率低:要将原始数据删除,同时后面每个数据前移。
  • 添加效率较低:添加位置后的每个数据后移,再添加元素。

链表

链表由一个个的结点组成,链表中的结点是独立的对象,在内存中是不连续的。每个结点包括数据和地址两部分:前面是数据,后面是下一个结点的地址。

特点:查询慢,增删快

单向链表

查找时从头到尾,并且一个结点只有数据和后一结点的地址。

双向链表

查找时先分析,要查找的离头近还是离尾近,再进行查找。此时一个结点包含数据,前一结点地址和后一节点地址。

树由许多的节点组成,最上层的节点被称为,最下层的节点被称为

此外,上下层结点间又分为父节点和子节点的关系,一个父节点可以拥有两个子节点:左子结点右子节点

在一个节点中,包含:

  • 父节点地址
  • 左子节点地址
  • 右子节点地址

根没有父节点地址,叶没有子节点地址。

二叉树

定义:任意节点的度<=2的树

  • 度:每个节点的子节点数量
  • 树高:树的总层数

二叉查找树

定义:二叉查找树,又称二叉排序树或者二叉搜索树

特点

  • 每一个节点上最多有两个子节点
  • 任意节点左子树上的值都小于当前节点
  • 任意节点右子树上的值都大于当前节点

添加规则:小的存左边,大的存右边,一样的不存。

查找规则:逐一比较,比根小的查左边,比根大的查右边。

遍历方式

  1. 前序遍历:当前节点,左子节点,右子节点

  2. 中序遍历:左子节点,当前节点,右子节点

  3. 后序遍历:左子节点,右子节点,当前节点

  4. 层序遍历:一层一层去遍历

弊端:若添加的节点一个比一个大,最后会形成链表而非树。

平衡二叉树

规则:任意节点左右子树高度差不超过1

注意,这里的“任意”指的是这个数中的任意,而非有关联的任意,也就是说根也需要算入其中。

平衡二叉树旋转机制

这个机制是用来保证平衡二叉树的规则能够正常成立的。

  • 规则1:左旋
  • 规则2:右旋
  • 触发时机:当添加一个节点之后,该树不再是一颗平衡二叉树。
左旋

核心

确定支点:从添加的节点开始,不断地往父节点找不平衡的节点。

  1. 支点没有左子结点:
  • 以不平衡的点为支点
  • 把支点左旋降级,变成左子结点
  • 晋升原来的右子节点

通俗一点理解可以是,一个正级干部犯了错,破坏了平衡,就得被降级,然后他之前的下一级干部上来顶替他的位置。

  1. 支点有左子结点:
  • 以不平衡的点作为支点
  • 将根节点的右侧往左拉
  • 原先的右子节点变成新的父节点,并把多余的左子结点出让,给已经降级的根节点当右子节点。
右旋

核心与左旋一致。

  1. 支点没有右子节点:
  • 以不平衡的点为支点
  • 把支点右旋降级,变成右子结点
  • 晋升原来的左子节点
  1. 支点有右子节点:
  • 以不平衡的点作为支点
  • 将根节点的左侧往右拉
  • 原先的左子节点变成新的父节点,并把多余的右子结点出让,给已经降级的根节点当左子节点。
需要旋转的四种情况
  • 左左:当根节点左子树的左子树有节点插入,导致不平衡

一次右旋。

  • 左右:当根节点左子树的右子树有节点插入,导致不平衡

在这里我们需要将左右转换成左左,再去进行右旋才能平衡。

  • 右右:当根节点右子树的右子树有节点插入,导致不平衡

一次左旋。

  • 右左:当根节点右子树的左子树有节点插入,导致不平衡

先将右左转换成右右,也就是进行一次局部右旋,再去进行左旋。

红黑树

基本概念
  • 红黑树是一种自平衡的二叉查找树,是计算机科学中用到的一种数据结构。
  • 它是一种特殊的二叉查找树,红黑树的每一个节点上都有存储位表示节点的颜色。
  • 每一个节点可以是红或者黑,红黑树不是高度平衡的,它的平衡是通过“红黑规则”进行实现的。
  • 红黑树增删改查的性能都很好。
红黑规则
  1. 每一个节点是红色或者黑色的
  2. 根节点必须是黑色
  3. 如果一个节点没有子节点或者父节点,则该节点相应的指针属性值为Nil,这些Nil视为叶节点,每个都是黑色的。
  4. 如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连的情况)
  5. 对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。
添加规则

默认颜色:添加节点默认是红色的(效率高)

解释:若添加三个节点(包括根节点),默认是黑色时,我们需要把另外两个非根节点调整为红色,也就是2次;但默认是红色时,我们只需要把根节点调整为黑色,也就是1次。

:直接变为黑色

非根

情况一:父节点为黑色

不做任何操作。

情况二:父节点为红色

  1. 叔叔红色
  • 将“父”设为黑色,将“叔叔”设为黑色
  • 将“祖父”设为“红色”
  • 如果祖父为根,再将根变为黑色
  • 如果祖父非根,将祖父设置为当前节点再进行其他判断
  1. 叔叔黑色,当前节点是父的右孩子
  • 把父作为当前节点并左旋,再进行判断
  1. 叔叔黑色,当前节点是父的左孩子
  • 将“父”设为“黑色”
  • 将“祖父”设为“红色”
  • 以祖父为支点进行右旋