乍一看,集合的体系还是相当大的,需要快速掌握对集合各种类的使用环境需要对其底层的数据结构进行了解掌握。我在此就分享一下集合中涉及以及一些常用的数据结构。java集合框架中涉及的数据结构有与ArrayList中数组类似的顺序表,LinkedList中的双端队列链表,Stack的栈,以及TreeMap中的红黑树。
一、线性表(LinearList)
线性表:是n(n≥0)个具有相同类型的数据元素的有限序列。
1、顺序表--线性表的顺序结构
顺序表:用一组地址连续的存储单元一次存放线性表的元素。设顺序表中放入的数值依次为1、2、3等,则其存储结构图如下:
从上面的图形就可以很快发现,顺序表与一维数组相似,顺序表的底层是靠数组来实现的。顺序表是一种随机存取的存储结构,依靠下标进行查询,因此效率高,但增删操作时,需要移动大量元素。
2、链表--线性表的链式存储结构
链表:采用一组地址任意的存储单元存放线性表中的元素,链式结构的线性表不会按照线性的逻辑顺序来保存数据元素,他需要在每一个元素中保存一个指向下一个元素的引用。
链表的基本存储结构单元:有序元素需要保存下一个元素的引用, 因此,其结构单元中具有data存放内容,next存放下一个元素的引用,如图
单链表--最简单的链表
单链表:由一组存储单元连接而成,结构图如下,
单链表的操作有查找,添加,删除,修改,现演示单链表的插入过程如下
3、顺序表与链表的比较
⑴若线性表需频繁查找却很少进行插入和删除操作,或其操作和元素在表中的位置密切相关时,宜采用顺序表作为存储结构;若线性表需频繁插入和删除时,则宜采用单链表做存储结构。
⑵当线性表中元素个数变化较大或者未知时,最好使用单链表实现;而如果用户事先知道线性表的大致长度,使用顺序表的空间效率会更高。
二、特殊线性表
当规定线性表的插入与删除操作后,就出现了特殊的线性表,常用的有栈与队列
1、栈
栈:遵循后进先出的原则,新加入的元素添加至栈底,而读取数据时从栈顶开始弹出数据。就像读书时交作业本与发作业本,交作业相当于添加元素,即进栈,而发作业相当于读取数据,即弹栈、出栈。栈的作业方式如下图
栈的顺序存储结构图以及入栈操作:
栈的链式存储结构
顺序栈与链栈:
顺序栈:有元素个数的限制和空间浪费的问题。
链栈:没有栈满的问题,只有当内存没有可用空间时才会出现栈满,但是每个元素都需要一个指针域,从而产生了结构性开销。
当栈的使用过程中元素个数变化较大时,用链栈是适宜的,反之,应该采用顺序栈。
2、队列
队列:遵循先进先出的原则,只能在队头进行删除元素,队尾添加元素,如打饭排队,一个个排队的时候相当于入队,而打完之后出来相当于出队
队列的逻辑结构图:
队列的顺序结构:队列结构需要有两个指针,队头与队尾,添加元素时,队尾指针移动,删除元素时,队头指针移动,但是随着元素的不断删减,当两个指针均指向队尾的时候,就会出现假溢出的情况,情况如下所示。
假溢出:队列中实质没有数据,但是由于添加元素时,队头指针指向最队列末端,无法再继续添加元素,因此抛出溢出异常。
为了解决假溢出的问题,因此出现了循环队列。将队列头尾相接,便形成了圆形的循环队列,循环队列结构图,以及添加元素操作如下图所示
队列的链式结构:由于链式结构是分配在不连续地址空间,因此只要硬盘不满,永远也不用担心队列溢出的问题,因此只需在单链表的基础上加上两个指针即可,链式结构的实现如下图:
双向队列的链式结构:一种特殊的队列,他可以在两端同时进行插入、删除,若将所有的插入删除操作放在一段进行,则就会变成前面介绍的栈,因此在集合框架中的Deque(双向队列)接口继承队列(Queue)接口与栈(Stack)接口;因此双向队列的基础结构单元有三部分,data,previous,next,其结构,以及双向队列的结构如下图:
3、红黑树
树:非线性结构,结构内的元素存在着一对多的关系,树的结构比前面的线性结构要复杂。自然中,树最重要的便是树根、树干、树叶,在计算机中将树根与树叶抽取出来分别作为树的根节点、叶子节点,那么树干,就是其关系的纽带。
二叉树:每个节点最多只能有两个子树的有序树。由于普通书遵循的规律太少,程序控制起来较麻烦,限制了它在实际应用中的使用,因此便对其进行限制。
满二叉树:除最后一层外,树的所有节点都有两个子节点的二叉树,便是满二叉树。
完全二叉树:若一棵有n个节点的树,按照树的结构从上往下,层层编号(层序遍历),若树中的所有节点和满二叉树1~ n的编号一致,则是完全二叉树。
二叉树的存储结构:二叉树的存储结构有多种,现在介绍一种,二叉链表存储,其基本存储单元为lchild,data,rchild,即左子树,数据,右子树。
二叉链表的基本存储单元:
用二叉链表表示一棵二叉树:
排序二叉树的特点:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
排序二叉树的实现步骤,其实就是不断向排序二叉树添加节点的过程:
(1)以根节点为当前节点开始搜索
(2)拿新节点的值与当前节点的值比较
(3)如果新节点的值更大,则以当前节点的右子节点作为当前节点搜索,从(1)处开始循环;如果新节点的值更小,则以当前节点的左子结点作为当前节点搜索,也从(1)处开始循环;直到找出合适的叶子节点。
(4)当值比当前叶子节点大,将新值添加到叶子节点的右子树,反之,添加到左子树。
当插入的节点本来就有序的时候,那么排序二叉树就变成了一个链表结构,检索效率就会非常慢,因此为了解决这一问题,便就有了红黑树。TreeMap就是红黑树的实现。
红黑树:红黑树通过自定义的条件限制排序二叉树出现的高度极端化,他控制二叉树的高度区域平衡,这样就提高了效率。
红黑树在原有排序二叉树增加的要求:
数据结构的学习是一个繁琐的过程,我的博客只是简单分析一些最基础的东西,要是大家想学好,仍需多钻研,因为树的结构太过复杂,就不一一画图展示。若有错误之处,大家多多指正,谢谢。