1.栈
模型:
栈模型和一个杯子差不多,一端开口,一端封闭,开口的那端叫栈顶,封闭的那端叫栈底,如图所示
介绍:
元素进入栈中叫进栈/压栈,元素出来叫出栈,元素进栈后会先来到栈底,再进栈的元素会垒到上一个进栈的元素的上方,距离栈顶最近的即最上方的元素为栈顶元素,每次出栈就是将栈顶元素出栈。可以理解为向弹夹中压子弹。
特点:
栈的特点是先进后出,后进先出,即先进去的元素会后出来,后进去的元素先出来
2.队列
模型:
队列模型两端都是开口的,一端为前端,一端为后端
介绍:
元素进入队列从后端进,会先来到最靠近前端的位置,后续元素继续进入队列会排到前一个元素的后面,元素出队列会从前端出,最靠近前端的元素先出。可以理解为排队的队伍。
特点:
队列的特点是先进先出,后进后出。
3.数组
模型:
特点:
数组中的元素在内存中是连续存储的。
查询速度快:通过地址值和索引定位查询数据,查询任意数据耗时相同
删除效率低:要将原始数据删除,还需将后面每个数据前移
添加效率低:添加数据后的每个数据需后移,再添加元素
4.链表
介绍:
链表中的元素为结点,每个结点中都要存储具体的数据和下一个结点的地址,如下图所示。
模型:
在链表中第一个创建出来的结点为头结点,头结点创建完后,他可以存储具体的数据,同时下一个结点的地址存储的为^,表示空地址,因为这个结点后面没有其他结点了。
如果已经创建了一个链表的头结点,需要再添加一个数据A,那么接下来的步骤应该是先创建一个新的结点,新结点存储数据A,下一个结点地址为^,然后将头结点存储的下一个结点的地址赋值为新结点的地址。如下图所示
再添加数据C和数据D呢,如下图所示
特点:
链表中的结点是独立的对象,在内存中是不连续的,每个结点包含数据值和下一个结点的地址。
(相较于数组来说)
查询慢,无论查询哪个数据都要从头开始找。
增删块,只需改变存储的下一个结点的值加删除结点就能完成增删操作。
双向链表模型:
5.树
模型:
如图所示,树是由节点(结点)组成,16是15和17的父节点,15是16的左子节点,17是16的右子节点。
而每个节点中存储的值由下图所示
每个节点中都存储着自己存储的值,父节点地址,左子节点地址,右子节点地址。若哪个节点没有,那么存储的地址值置为null。
术语:
度:每一个节点的子节点数量
树高:树的总层数,上文中的树树高为4,从上到下依次为第一层、第二层、第三层、第四层
根节点:最顶层的节点,上文中的树即22
左子节点:左下方的节点
右子节点:右下方的节点
根节点的左子树:根节点的左下方节点及其下方的所有节点连接起来的树
根节点的右子树:根节点的右下方节点及其下方的所有节点连接起来的树
二叉树
规则:
每一个节点的子节点数<=2
模型:
二叉树遍历方式:
(1)前序遍历
前序遍历即从根节点开始,按照当前节点、左子节点、右子节点的顺序遍历。
例如下图二叉查找树
其前序遍历的结果为 20,18,16,19,23,22,24
(2)★中序遍历
从最左边的子节点开始,然后按照左子节点,当前节点,右子节点的顺序遍历
例如下图二叉查找树
其中序遍历的结果为 16,18,19,20,22,23,24(这种遍历方法遍历二叉查找树得到的结果是由小到大的)
(3)后序遍历
从最左边的子节点开始,然后按照左子节点,右子节点,当前节点的顺序遍历
例如下图二叉查找树
其后序遍历的结果为 16,19,18,22,24,23,20
(4)层序遍历
从根节点开始,一层一层的遍历
例如下图二叉查找树
其层序遍历的结果为 20,18,23,16,19,22,24
二叉查找树(又叫做二叉排序树或二叉搜索树)
普通二叉树的弊端:
数据没有规律,查找很难,必须要遍历才能查找,效率很低,所以有了二叉查找树。
特点:
1.每一个节点上最多有两个子节点(即是二叉树)
2.任意节点左子树上的值都小于当前节点
3.任意节点右子树上的值都大于当前节点
模型:
添加节点规则:
从根节点开始逐个往下层比,小的放左边,大的放右边,重复的不放
查找结点规则:
从根节点开始逐个往下层比,查找元素比节点小跟其左子节点继续比,查找元素比节点大跟其右子节点继续比,直到找到或者节点的子节点为空,即没找到。
二叉查找树的弊端:
如果按顺序添加的元素正好是逐渐增大的,那么第一个元素为根节点,其他所有元素都会逐个排到最下层节点的右子节点位置,这样如果要查找最大的那个数据,查找效率还是很低,所以有了二叉平衡树。
平衡二叉树
规则:
任意节点的左右子树高度差不超过1
模型:
平衡二叉树的旋转机制:
平衡二叉树通过旋转机制来保证任意节点的左右子树高度差不超过1
触发机制:
当添加一个节点后,该树不再是一颗平衡二叉树
旋转方式:
1.左旋
支点不是根节点情况:
①确定支点:从添加的节点开始,不断的往父节点找不平衡的节点(左右子树高度差超过1)
②把支点左旋降级,变成左子节点
③晋升原来的右子节点
如图:
变成
支点为根节点:
①确定支点:从添加的节点开始,不断的往父节点找不平衡的节点(左右子树高度差超过1)
②将根节点的右侧往左拉
③原来的右子节点变成新的父节点,并把多余的左子节点出让,给已经降级的根节点当右子 节点
如图:
变成
2.右旋
支点不是根节点情况:
①确定支点:从添加的节点开始,不断的往父节点找不平衡的节点(左右子树高度差超过1)
②把支点右旋降级,变成右子节点
③晋升原来的左子节点
如图:
变成
支点为根节点:
①确定支点:从添加的节点开始,不断的往父节点找不平衡的节点(左右子树高度差超过1)
②将根节点的左侧往右拉
③原来的左子节点变成新的父节点,并把多余的右子节点出让,给已经降级的根节点当左子 节点
如图:
变成
平衡二叉树需要旋转的四种情况:
1.左左
当根节点的左子树的左子树有节点插入,导致二叉树不平衡
这种情况需要进行一次右旋
如图:
变成 ↓ ↓
2.左右
当根节点的左子树的右子树有节点插入,导致二叉树不平衡
这种情况需要对根节点的左子树进行一次左旋,再整体进行一次右旋
如图:
变成
变成
3.右右
当根节点的右子树的右子树有节点插入,导致二叉树不平衡
这种情况需要进行一次左旋
如图:
变成
4.右左
当根节点的右子树的左子树有节点插入,导致二叉树不平衡
这种情况需要对根节点的右子树进行一次右旋,再整体进行一次左旋
如图:
变成
变成
红黑树
红黑树是一种自平衡的二叉查找树,它的每一个节点上都有存储位表示节点的颜色,每一个节点可以是红是黑,它不是高度平衡的,它的平衡是通过“红黑规则”进行实现的。
红黑树的增删改查性能都很好。
红黑规则:
①每一个节点都是红色或者黑色
②根节点必须是黑色
③如果一个节点没有子节点或者父节点,则该节点相应的指针属性值为Nil,这些Nil视为叶节 点,每个叶节点(Nil)都是黑色的
④如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连的情 况)
⑤对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点
(后代叶节点:该节点下面的叶节点 简单路径:只能前进不能回头的路径)
模型:
红黑树添加节点规则:
首先要满足红黑规则
添加节点时,添加的节点默认为红色的,添加效率更高
下面是一些情况的解决方案:
(旋转时不用管叶节点,旋转后加上叶节点即可)