mysql---金丹篇(一)---数据结构之二叉树
1、问答
1、红黑树了解么,时间复杂度?
2、什么是B+树素引?为什么使用B+树?BTree机制说一下?B+tree 如何进行优化?二叉树的转置是什么?
MySQL索引类型有?如何管理 MySQL索引?什么是索引?什么是索引覆盖?什么是聚簇索引?什么是非聚簇索引?对比一下B+树索引和 Hash索引?什么是联合索引?
索引利弊是什么及索引分类?各自索引有哪些优缺点?浅谈索引优化?
聚簇索引和非聚簇索引的区别?
索引遵循哪些原则?存储引擎会进行哪些自动优化?到底何时索引会失效?
索引与锁有什么关系?
讲讲Innodb行锁?
死锁及监控是什么?
自增长与锁 ,锁的算法,锁问题,锁升级是什么?
谈谈MySQL的锁并发?
乐观锁是怎样的?
乐观锁悲观锁区别是什么?
数据库如何实现悲观锁和乐观锁?
数据库锁和隔高级别有什么关系?
数据库锁和索引有什么关系?
索引最左前缀是什么?
MySQL表设计及规范?
什么是回表?
讲讲表与表之间的关系?分库分表,设计可动态打容缩的分库分表,分库分表之后全局id的生成
MySQL读写分离及主从同步延时解决方案,MySQL主从复制怎么实现的?具体原理是什么?有什么优缺点?
InnoDB支持的四种事务隔离级别名称是什么?有什么却别?说说MySQL隔离级别?
事务的特性及慢查询?
说说MySQL常用的优化方法?对Explain参数及重要参数的理解?
说说MySQL几种存储引擎应用场景?都有什么区别?
谈谈对Innodb事务的理解?
说说数据库事务特点及潜在问题?
什么是MySQL隔离级别?
有多少种事务失效的场景,如何解决?
Innodb如何解决幻读?
了解查询优化器模块;
查询优化的基本思路是什么?
说说MySQL读写分离、分库分表?
JOIN的原理是什么?
Query语句对数据库性能有什么影响?
表结构对性能有什么影响?
MySQL瓶颈分析?说说Sql优化的几点原则?MySQL常用优化方式有哪些?
MySQL常用监控?
2、树的演进过程
基本概念
双亲—— 孩子结点的上层结点叫该结点的双亲 兄弟—— 同一双亲的孩子之间互成为兄弟 祖先—— 结点的祖先是从根到该结点所经分支上的所有结点 子孙—— 以某结点为根的子树中的任一结点都成为该结点的子孙 结点的层次—— 从根结点算起,根为第一层,它的孩子为第二层…… 堂兄弟—— 其双亲在同一层的结点互称为堂兄弟。 有序树—— 如果将树中结点的各子树看成从左至右是有次序的(即不能互换),则称该树为有序树,否则称为无序树。在有序树中最左边的子树的根称为第一个孩子,最右边的称为最后一个孩子。 森林—— m(m>0)棵互不相交的树的集合
2.1 树
树是互不相交的n个节点(n>=0)有限集.
n=0时称为空树.
n=1时仅有一个根节点。
当n>1时,其余结点可分为个互不相交的有限集(T1、T2、......、Tn),其中每一个集合又是一棵树,并且称为根的子树。子树的个数没有限制,但它们一定是互不相交的
树的度:结点拥有的子树数目或最大分支数称为结点的度。如图A节点有b、c2个子树,她的度为2,J节点没有子树,它的度为0。
树的深度:树中结点的最大层次数称为树的深度或高度。如图所示树的深度为4。
叶子结点:度为0的结点,即没有子节点。如GHIJ都是叶子节点。
内部结点:也叫中间节点,除去根节点和叶子节点的其它节点。

2.2 二叉树
二叉树即每个结点都最多只有两个子结点的树。
二叉树有以下特点:
1)每个结点最多有两棵子树,所以二叉树中不存在度大于2的结点。
2)左子树和右子树是有顺序的,次序不能任意颠倒。
3)即使树中某结点只有一棵子树,也要区分它是左子树还是右子树
二叉树性质
1)在二叉树的第i层上最多有2i-1 个节点 。(i>=1)
2)二叉树中如果深度为k,那么最多有2k-1个节点。(k>=1)
3)n0=n2+1, n0表示度数为0的节点数,n2表示度数为2的节点数。
4)在完全二叉树中,具有n个节点的完全二叉树的深度为[log2n]+1,其中[log2n]是向下取整。
5)若对含 n 个结点的完全二叉树从上到下且从左至右进行 1 至 n 的编号,则对完全二叉树中
2.2.1 普通二叉树

2.2.2 斜树
所有的结点都只有左子树的二叉树叫左斜树。所有结点都是只有右子树的二叉树叫右斜树。这两者统称为斜树。


2.2.3 完全二叉树
若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1层) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
如图,第一幅图,1~2层每层都达到了最大节点数。第二幅图,第一层有1个节点,第二层有2个节点,第三层有4个节点,都达到了最大节点数。
2.2.3 满二叉树
美国以及国际上所定义的满二叉树,即full binary tree,和国内的定义不同
国际定义的满二叉树:除叶子节点外,每个结点都有左右子结点的二叉树。即树的结点要么是度为0的叶子结点,要么是度为2的结点,不存在度为1的结点。
国内定义的满二叉树:高度为h,由2^h-1个节点构成的二叉树称为满二叉树。即根节点左右子节点层级相同,除了最后一层外,其它各层节点度都为2.
国际定义的满二叉树 国内定义的满二叉树:
2.2.4 二叉查找树
二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree),也称为有序二叉查找树,它是一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的结点。
如果以6为根节点,依次插入6、3、7、8、2、5,它的机构如下
按照中序遍历的方式可以从小到大的顺序排序输出:2、3、5、6、7、8,下面演示使用2种查找方式查找数值为8的数
顺序查找:先找到2,不是8;再找到3,不是8;...直到按顺序找到8,共找了6次。所有数都按顺序查找的平均查找次数为(1+2+3+4+5+6)/ 6 = 3.3次。
二叉树进行查找:先找到根,其键值是6,6小于8,因此查找6的右子树;找到7;而7小于8;再找其右子树,直到找到8;一共找了3次。二叉查找树的平均查找次数为(3+3+3+2+2+1)/6=2.3次。
由此可见:二叉查找树的平均查找速度比顺序查找来得更快。
但是随着节点的添加和删除,二叉查找树会退化为线性树。
例如:如果根节点选择是最小或者最大的数,如根节点是2,数字以2、3、5、6、7、8顺序插入,按二叉查找树排序,就完全退化成了线性结构
平均查找次数为(1+2+3+4+5+6)/6=3.3次,和顺序查找差不多,一颗二叉查找树的优势完全丧失了.
若想最大性能的构造一个二叉查找树,需要这个二叉树是平衡的,从而引出了一个新的定义-平衡二叉树AVL。
二叉树的应用场景:
普通的二叉树,很难构成现实的应用场景,但因其简单,常用于学习研究,平衡二叉树则是实际应用比较多的。常见于快速匹配、搜索等方面。
常用的树有:AVL树、红黑树、B+树、Trie(字典)树。
1、AVL树: 最早的平衡二叉树之一。应用相对其他数据结构比较少。windows对进程地址空间的管理用到了AVL树。
2、红黑树: 平衡二叉树,广泛用在C++的STL中。如map和set都是用红黑树实现的。还有Linux文件管理。
3、B/B+树: 用在磁盘文件组织 数据索引和数据库索引。
4、Trie树(字典树): 用在统计和排序大量字符串,如自动机、M数据库索引
2.2.5 平衡二叉树
平衡二叉树(Balanced Binary Tree)又被称为AVL树(有别于AVL算法),是一种高度平衡二叉树。
具有以下性质:
它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
它是严格的平衡二叉树,平衡条件必须满足(所有节点的左右子树高度差不超过1),不管我们是执行插入还是删除操作,只要不满足上面的条件,就要通过旋转来保持平衡,而旋转是非常耗时的,由此我们可以知道AVL树适合用于插入删除次数比较少,但查找多的情况。注意:在大量查找的情况下,平衡二叉树的效率更高,也是首要选择。在大量增删的情况下,红黑树是首选。
在插入的情况下平衡二叉树需要维持高度平衡,这也就意味着在大量插入和删除节点的场景下,需要调整的频率会更高
删除时,对于平衡二叉树来说,最坏情况下,需要维护从被删节点到根节点这条路径上所有节点的平衡性,旋转的量级是O(logN)。但是红黑树就不一样了,最多只需3次旋转就会重新平衡,旋转的量级是O(1)。
应用
Windows NT内核中广泛存在
2.2.6 红黑树
它是一种自平衡二叉查找树,也叫弱平衡二叉树,相对于要求严格的AVL树来说,它的旋转次数变少,所以对于搜索、插入、删除操作多的情况下,我们就用红黑树。
在二叉查找树基础上,添加以下性质
1.节点是红色或黑色。
2.根节点是黑色。
3.每个叶子节点都是黑色的空节点(NIL节点)。
4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)(新插入节点,刚开始都是红色)
5.从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
正式因为有了这些规则限制,才保证了红黑树的自平衡
时间复杂度为O(lgn),如图
当插入或删除的时候,红黑树规则可能被打破。什么情况下会破坏红黑树的规则,什么情况下不会破坏规则呢?
向原红黑树插入值为14的新节点,没破坏规则: 向原红黑树插入值为21的新节点,破坏了规则4(红色节点的子节点都是黑色)
必须进行调整,使之重新符合红黑树的规则,调整有2种方法
- 变色
- 旋转:左旋转和右旋转
变色:使用变色方法进行调整流程,如图
step1:把22变为黑色,凭空多出的黑色节点打破了规则5 step2:继续把节点25从黑色变成红色,发生连锁反应 step3:继续把红色节点27变为黑色
左旋转:逆时针旋转红黑树的两个节点,使得父节点被自己的右孩子取代,而自己成为自己的左孩子。
如图:身为右孩子的Y取代了X的位置,而X变成了自己的左孩子。此为左旋转
右旋转:顺时针旋转红黑树的两个节点,使得父节点被自己的左孩子取代,而自己成为自己的右孩子。
如图:身为左孩子的Y取代了X的位置,而X变成了自己的右孩子。此为右旋转
下面我们以刚才插入节点21的情况为例,演示是使用变色还是旋转。
先使用变色,把节点25及其下方的节点变色,
此时节点17和节点25是连续的两个红色节点,那么把节点17变成黑色节点?这样一来不但打破了规则4,而且根据规则2(根节点是黑色),也不可能把节点13变成红色节点。
变色已无法解决问题,我们把节点13看做X,把节点17看做Y,像刚才的示意图那样进行左旋转:
由于根节点必须是黑色节点,所以需要变色,变色结果如下:
此时路径(17 -> 8 -> 6 -> NIL)的黑色节点个数是4,其他路径的黑色节点个数是3,不符合规则5。这时候我们需要把节点13看做X,节点8看做Y,像刚才的示意图那样进行右旋转
最后根据规则来进行变色:
如此一来,我们的红黑树变得重新符合规则。这一个例子的调整过程比较复杂,经历了如下步骤:变色 -> 左旋转 -> 变色 -> 右旋转 -> 变色
应用
1、广泛用于C++的STL中,Map和Set都是用红黑树实现的;
2、著名的Linux进程调度Completely Fair Scheduler,用红黑树管理进程控制块,进程的虚拟内存区域都存储在一颗红黑树上,每个虚拟地址区域都对应红黑树的一个节点,左指针指向相邻的地址虚拟存储区域,右指针指向相邻的高地址虚拟地址空间;
3、IO多路复用epoll的实现采用红黑树组织管理sockfd,以支持快速的增删改查;
4、Nginx中用红黑树管理timer,因为红黑树是有序的,可以很快的得到距离当前最小的定时器;
5、Java中TreeMap的实现;
2.2 二叉树遍历
前序遍历(前根遍历):根——>左——>右
中序遍历(中根遍历):左——>根——>右
后序遍历(后根遍历):左——>右——>根
层次遍历:层次从上到下,每层从左到右
前序遍历
先序遍历:(1)访问根节点;(2)先序递归遍历左子树;(3)先序递归遍历右子树;
先序遍历结果:A BDFE CGHI
中序遍历
中序遍历:(1)中序遍历左子树;(2)访问根节点;(3)中序遍历右子树
中序遍历结果:DBEF A GHCI
后序遍历
后序遍历:(1)后序递归遍历左子树;(2)后序递归遍历右子树;(3)访问根节点;
后序遍历的结果:DEFB HGIC A
层序遍历
从树的第一层,也就是根节点开始访问,从上到下逐层遍历,在同一层中,按从左到右的顺序结点逐个访问。
2.3 二叉树村存储结构
2.3.1 顺序存储
二叉树的顺序存储,就是用一组连续的存储单元存放二叉树中的结点。因此,必须把二叉树的所有结点安排成为一个恰当的序列,用编号的方法从树根起,自上层至下层,每层自左至右地给所有结点编号,缺点是有可能对存储空间造成极大的浪费,在最坏的情况下,一个深度为k且只有k个结点的右单支树需要2k-1个结点存储空间。
依据二叉树的性质,完全二叉树和满二叉树采用顺序存储比较合适,树中结点的序号可以唯一地反映出结点之间的逻辑关系,这样既能够最大可能地节省存储空间,又可以利用数组元素的下标值确定结点在二叉树中的位置,以及结点之间的关系。
存储在数组中
最差的情况如下,线性结构的二叉树,对存储空间造成了极大的浪费
其中,∧表示数组中此位置没有存储结点
2.3.2 链式存储结构
由二叉树定义可知,二叉树的每个结点最多有两个孩子。因此,可以将结点数据结构定义为一个数据和两个指针域,这种链表叫做二叉链表,如图
节点代码
typedef struct BiTNode{ TElemType data;//数据 struct BiTNode *lchild, *rchild;//左右孩子指针 } BiTNode, *BiTree;
为了方便访问某结点的双亲,还可以给链表结点增加一个双亲字段parent,用来指向其双亲结点。每个结点由四个域组成,其结点结构为:
这种存储结构既便于查找孩子结点,又便于查找双亲结点;但是,相对于二叉链表存储结构而言,它增加了空间开销。利用这样的结点结构表示的二叉树的链式存储结构被称为三叉链表。
节点代码
#define datatype char //定义二叉树元素的数据类型为字符 typedef struct node { //定义结点由数据域,左右指针组成 Datatype data; struct node *lchild,*rchild,*parent; }Bitree;
3、时间复杂度的规则与计算
最优时间复杂度:算法完成工作最少需要多少基本操作.其反映的只是最乐观最理想的情况,没有参考价值.
最坏时间复杂度:算法完成工作最多需要多少基本操作.提供了一种保证,表明算法在此种程度的基本操作中一定能完成工作
平均时间复杂度 :算法完成工作平均需要多少基本操作.是对算法的一个全面评价,因此它完整全面的反映了这个算法的性质
时间复杂度的几条基本计算规则
基本操作,即只有常数项,认为其时间复杂度为O(1)
顺序结构,时间复杂度按加法进行计算
循环结构,时间复杂度按乘法进行计算
分支结构,时间复杂度取最大值
判断一个算法的效率时,往往只需要关注操作数量的最高次项,其它次要项和常数项可以忽略
在没有特殊说明时,我们所分析的算法的时间复杂度都是指最坏时间复杂度
常见时间复杂度
执行次数函数举例 | 阶 | 非正式术语 |
---|---|---|
12 | O(1) | 常数阶 |
2n+3 | O(n) | 线性阶 |
3n2+2n+1 | O(n2) | 平方阶 |
5log2n+20 | O(logn) | 对数阶 |
2n+3nlog2n+19 | O(nlogn) | nlogn阶 |
6n3+2n2+3n+4 | O(n3) | 立方阶 |
2n | O(2n) | 指数阶 |
注意,经常将log2n(以2为底的对数)简写成logn。lne2(以e为底的对数)写成ln2
所消耗的时间从小到大
O(1) < O(logn) < O(n) < O(nlogn) < O(n2) < O(n3) < O(2n) < O(n!) < O(nn
参考文档:
B-Tree,B+Tree以及mysql索引的实现
https://blog.csdn.net/sinat_36722750/article/details/82946311
MySQL系列-B+Tree索引详解
https://blog.csdn.net/UFO___/article/details/80522453
MySQL系列-系统架构及存储引擎介绍
https://blog.csdn.net/UFO___/article/details/80519309
B树和B+树数据结构及使用场景
https://blog.csdn.net/qq_38238296/article/details/88362635
B+Tree原理及mysql的索引分析
https://www.cnblogs.com/xiaoxi/p/6894610.html
B树B-树和B+树的总结
https://open.toutiao.com/a6769472742832996877/?utm_medium=webview&vivo_news_comment_data=%7B%7D&vivo_news_source=1&vivo_news_comment_data_checksum=99914b932bd37a50b983c5e7c90ae93b&isNews=1&showOriginalComments=true&req_id=2019121407544801001401904422B9180D&crypt=5587&item_id=6769472742832996877&showComments=0&gy=2a8d3612778e2cf097372a2c3a21dbad1b3466d040348083237cf2e45b94fdae358665bc74c6eb1485e5ed19d06eb230ef07bc4c534673942907ea174cb240234e97a27571915331963ea79749950d97008d4d721550dcf23dd5b9d8078da4e95ac249bc39c77ad5b9ec78d61e6be56d4c671cd609e027502ed387b925fb8e55280e2d9ecd4449ba09ed1e322d0431d6&a_t=31158380437568786751332dce1&label=vivo_llq_channel&utm_source=vivoliulanqi&utm_campaign=open&dt=vivo%20X9
看了这么多篇红黑树文章,你都理解了嘛?
https://open.toutiao.com/a6739678098108711432/?utm_medium=webview&vivo_news_comment_data=%7B%7D&vivo_news_source=1&vivo_news_comment_data_checksum=99914b932bd37a50b983c5e7c90ae93b&isNews=1&showOriginalComments=true&req_id=2019121408465801001206109423C40CD0&crypt=5268&item_id=6739678098108711432&showComments=0&gy=3006ce77496da435474b365b461bf44c6208c62d614f95dfaef6027f46771e10eba35c9791f6b165a2dc39bfd342c647436bc06dd9513d69ece08f40c907ce161262e9bafa1d98434c5aa5fb5799521e201f63d8000ed340474acf3a8bed77b9c85df43c567c0bf5f6a9efd562042978098f5354fb346ccaecd4e890624fa4580b151f42488829a33af707fadfdbd5fe&a_t=31158380437568786751332dce1&label=vivo_llq_channel&utm_source=vivoliulanqi&utm_campaign=open&dt=vivo%20X9
什么是红黑树?(画图讲解,比较容易理解)
https://blog.csdn.net/qq_36610462/article/details/83277524
复杂度分析(大O表示法)
https://blog.csdn.net/weixin_42313246/article/details/108315179
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」