数组

数组是可以在内存中连续存储多个元素的结构,在内存中的分配也是连续的,数组中的元素可以通过数组下标进行访问,数组下标从0开始。

优点:

  1. 按照索引查询元素速度快
  2. 按照索引遍历数组方便

缺点:

  1. 数组的大小固定后就无法扩容了
  2. 数组只能存储一种类型的数据
  3. 添加,删除的操作慢,因为要移动其他的元素。

适用场景:

频繁查询,对存储空间要求不大,很少增加和删除的情况

二叉排序树

二叉排序树是基于二分法的策略提高数据的查找速度的二叉树的数据结构

  • 左子树上所有结点的值均小于或等于它的根结点的值。
  • 右子树上所有结点的值均大于或等于它的根结点的值。
  • 左、右子树也分别为二叉排序树。

队列

队列也是一种线性表,不同的是,队列可以在一端添加元素,在另一端取出元素,也就是:先进先出。 从一端放入元素的操作称为入队,取出元素为出队

链表

链表是物理存储单元上非连续的、非顺序的存储结构,每个链表元素包含两块内容,一个是存储元素的数据域,另一个是指向下一个结点地址的指针域。根据指针的指向,链表能形成不同的结构,例如单链表,双向链表,循环链表等。

优点:

  1. 链表是很常用的一种数据结构,不需要初始化容量,可以任意加减元素;

  2. 添加或者删除元素时只需要改变前后两个元素结点的指针域指向地址即可,速度快;

缺点:

  1. 因为含有大量的指针域,占用空间较大
  2. 查找元素需要遍历链表来查找,非常耗时

适用场景:

数据量较小,需要频繁增加,删除操作的场景

跳表

跳表可以解决有序链表查找插入慢的问题,思路是在有序列表的基础上,增加多级索引,又是一个典型的空间换时间的数据结构

每一层都是一个有序链表,上一层有指针指向下一层

栈是一种特殊的线性表(内存连续),仅能在线性表的一端操作,栈顶允许操作,栈底不允许操作。

栈的特点是:先进后出,或者说是后进先出,从栈顶放入元素的操作叫入栈,取出元素叫出栈。

栈常应用于实现递归功能方面的场景

Hash表

散列表,也叫哈希表,是根据关键码和值 (key和value) 直接进行访问的数据结构,通过key和value来映射到集合中的一个位置,这样就可以很快找到集合中的对应元素。

记录的存储位置=f(key)

这里的对应关系 f 成为散列函数,又称为哈希 (hash函数),而散列表就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里,这种存储空间可以充分利用数组的查找优势来查找元素,所以查找的速度很快。

哈希表在应用中也是比较常见的,就如Java中有些集合类就是借鉴了哈希原理构造的,例如HashMap,HashTable等,利用hash表的优势,对于集合的查找元素时非常方便的,然而,因为哈希表是基于数组衍生的数据结构,在添加删除元素方面是比较慢的,所以很多时候需要用到一种数组链表来做,也就是拉链法。拉链法是数组结合链表的一种结构,较早前的hashMap底层的存储就是采用这种结构,直到jdk1.8之后才换成了数组加红黑树的结构,其示例图如下

哈希表示意图