Java数据结构

数组


数组在内存中占据一段连续的内存空间,大小是固定的。在数组中插入数据,需要移动插入位置后的所有数据,这一特性使得数组对于插入操作并不友好。但数组对于位置的访问是极其友好的,就ArrayList来讲,它支持所谓RandomAccess特性,可以迅速完成基于位置的操作。

所以数组的最大优势是:基于位置的访问(查找时需要对比)。对于支持RandomAccess,迭代会比for循环快。

链表


链表不具备RandomAccess特性,链表是通过指针域来关联数据之间的位置关系,在内存中可以不是连续的地址,这使得链表的访问必须从头开始。而对于插入,删除,只需要操作对应前后的指针,修改指针域即可。

所以链表对查询访问是不太友好的,但对插入删除比较友好。

Hash散列


数组的优势是基于位置的访问,而链表的优势是增删操作。数组和链表在查询时表现一般的原因在于它们并不记得数据的位置,都需要用待查询的数据与存储的数组对比。
而 Hash散列,以key-value的形式存储数据,key****哈希后对应数组的位置,而数组对位置的访问是有优势的,所以这样可以优化对数据的查找(用到了数组的位置访问优势,同时又避免或减少了查找时的对比操作)。

使用 Hash算法来将key转换成int(对应数组下标),每次查找只要Hash一下,就可以取对应位置的value。这就是Hash散列。

但是对Hash算法来说,很难保证不会出现两个不同的key对应同一个int值,这就是所谓的哈希碰撞。对于这种情况,我们可以将value以链表的形式存储。


树(tree)是n个结点的有限集,n为0时则为空树。在任意一棵非空树中:

  1. 有且仅有一个特定的称为根(root)的结点;
  2. 当n>1时,其余结点可分为m(m>0)个互补相交的有限集,其中每一个集合本身又是一棵树,并且称为根的子树(subtree)。

有序树:如果将树中结点的各子树看成从左至右是有次序的,不能互换的,则称该树为有序树,否则称为无序树。

二叉排序树:它或者是一棵空树,或者具有以下性质:

  • 若它的左子树不为空,则左子树上所有的结点的值均小于它的根结点的值。
  • 若它的右子树不为空,则右子树上所有的结点的值均大于它的根结点的值。
  • 它的左右子树也分别为二叉排序树。
    (二叉排序树,可以看作是一个可二分查找的链表)

平衡二叉树(AVL Tree)
平衡二叉树是在二叉排序树的基础上,解决极端二叉排序树查询效率问题。如1-n的序列,如果以1或n为根结点,那么这个二叉树的层级为n,大大降低二叉排序树的查询效率,而平衡二叉树就是通过旋转的方式,找到合适的根结点,使得平衡因子(二叉树上左子树与右子树的深度之差)为 -1、0和1。

红黑树
红黑树的规则保证了插入、删除操作之后树的平衡,使得查找的最坏负责度都为O(logn)。

  • 根结点永远是黑色的。
  • 每个结点,要么是红色的,要么是黑色的。
  • 所有的 NIL / NULL 结点都是黑色的(都以NIL / NULL结尾)。
  • 每个红色结点的两个子结点一定都是黑色(不会有两个连续的红色结点,可以有连续的两个黑色结点)。
  • 从任一结点到其子树中每个叶子结点的路径都包含相同数量的黑色结点。

你可能感兴趣的:(Java数据结构)