数组:内存中连续的一块区域。因为是连续的区域,所以搜索比较快(按下标随机访问元素)。插入和删除因为要对其他数据进行移动,所以比较慢。删除操作有个优化,并不是真删除,而是给删除标识,等存储的数据空间达到阈值,进行统一删除操作。
链表:内存存非连续的区域,存储数据的内存中有两个区域,一个数据,一个是下一个数据的地址。 充分利用碎片的空间,插入删除比较容易,搜索时要从第一处一步一步往后搜。
引生出来的有双向链表,循环链表,双向循环链表。
栈:先进后出。数组和链表都可以组成栈。
利用两个栈实现浏览器的亲近和后退。每新开一个页面,将页面存到a栈中,后退时出栈,然后把出去来的页面存到b栈里,前进时从b栈里取到a栈里。
队列:先进先出。数组和链表都可以组成栈队列。
循环队列,阻塞队列,并发队列。并发队列:基于数组的循环队列,使用cas原子操作可以实现并发队列。 cas原子操作:有个预期值,版本号,值 入队和出队会比较预期值和版本号和携带的是否一致,一致则成功。
跳表:为链表增加索引,已达到快速查找的目的。
每隔一定数目建立一个索引链表,可以为索引列表再建立索引列表。
插入时使用随机数维持结构。
redis中有序集合的实现方式。
散列表(哈希表):通过key映射到数组下标的方法叫散列函数(哈希函数)。计算结果叫散列值(哈希值)。
散列冲突:两个key的散列值相等。
解决方法:
开放寻址法:线性探测。如果目标位置有值,就往后寻找空的位置,找到为止。
二次探测:线性探测的步长是1,二次探测则是12,22,3^…
双重散列:在用散列函数计算出来的有下标有值时,用第二个散列函数计算,然后第三个散列函数。直到有空为止。
ThreadLocalMap采用的是开放寻址法。装载因子不能过高。
优点:查找快,序列化容易。缺点:删除麻烦,更费内存空间。
链表法:将散列冲突的值组成一条链表。
适用于大对象,大数据量的存储
LinkedHashMap:采用的是双向链表+散列表的实现方式。支持LRU缓存淘汰原则。有序的
装载因子:数组有值得长度/数组长度,为了保证性能,会留有一定空间。
满二叉树:除最后一层无任何子节点外,每一层上的所有结点都有两个子结点。也可以这样理解,除叶子结点外的所有结点均有两个子结点。节点数达到最大值,所有叶子结点必须在同一层上。
完全二叉树:若设二叉树的深度为h,除第 h 层外,其它各层 (1~(h-1)层) 的结点数都达到最大个数,第h层所有的结点都连续集中在最左边,这就是完全二叉树。
二叉树的遍历:
前序遍历是指,对于树中的任意节点来说,先打印这个节点,然后再打印它的左子树,最后打印它的右子树。
中序遍历是指,对于树中的任意节点来说,先打印它的左子树,然后再打印它本身,最后打印它的右子树。
后序遍历是指,对于树中的任意节点来说,先打印它的左子树,然后再打印它的右子树,最后打印这个节点本身。
二叉查找树定义:又称为是二叉排序树(Binary Sort Tree)或二叉搜索树。二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
1) 若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
2) 若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
3) 左、右子树也分别为二叉排序树;
平衡二叉树定义:平衡二叉树(Balanced Binary Tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。平衡二叉树的常用算法有红黑树、AVL树等。在平衡二叉搜索树中,我们可以看到,其高度一般都良好地维持在O(log2n),大大降低了操作的时间复杂度。
B+树:mysql中索引的实现方式。是一种m叉树。
每个节点中子节点的个数不能超过m,也不能小于m/2;
根节点的子节点个数可以不超过m/2,这是一个例外;
根节点存储在内存上,其他节点存储在硬盘上。
通过双向链表将子叶节点连接起来。
m叉树只存储索引,并不真正存储数据,这个有点儿类似跳表;