一起来探索二叉树的奥秘
二叉搜索树是一种很常见的数据结构,维持了树中数据的全序性。本文先声明一点,此篇文章的中的二叉搜索树不允许重复节点出现。
![11f4e5ee02f41ed445adcab0ec2a48f5.gif](https://i-blog.csdnimg.cn/blog_migrate/46e44de3f4a78b0773615761e783a93b.gif)
![ca7b34cd03ffb3dd978cabb079ecffb1.png](https://i-blog.csdnimg.cn/blog_migrate/81c1466a92f52fe272672059e9dd2dff.png)
![11f4e5ee02f41ed445adcab0ec2a48f5.gif](https://i-blog.csdnimg.cn/blog_migrate/46e44de3f4a78b0773615761e783a93b.gif)
二叉搜索或者为空,或者具有如下性质:对任意一个结点p而言:
如果p的左子树若非空,则左子树上的所有结点的关键字值均小于p结点的关键字值。
如果p的右子树若非空,则右子树上的所有结点的关键字值均大于p结点的关键字值。
结点p的左右子树同样是二叉搜索树。
因此,在搜索一个目标值时;令当前节点为根节点,若目标值大于当前节点值,则深入当前节点右子树进行查找;反之,深入左子树进行查找。
![11f4e5ee02f41ed445adcab0ec2a48f5.gif](https://i-blog.csdnimg.cn/blog_migrate/46e44de3f4a78b0773615761e783a93b.gif)
![8f5d3a4e4099aa30954d425ca65e9a5d.png](https://i-blog.csdnimg.cn/blog_migrate/6fe019b0a2287afc31265c7b70d4ae08.png)
![11f4e5ee02f41ed445adcab0ec2a48f5.gif](https://i-blog.csdnimg.cn/blog_migrate/46e44de3f4a78b0773615761e783a93b.gif)
二叉搜索树的插入操作是最主要的操作之一,我们需要在插入的时候维持树的全序性,具体:
若二叉树为空。则新插入的结点成为根结点。
如二叉树非空
首先执行查找算法,找出被插结点的父亲结点。
判断被插结点是其父亲结点的左、右儿子。将被插结点作为叶子结点插入。
![11f4e5ee02f41ed445adcab0ec2a48f5.gif](https://i-blog.csdnimg.cn/blog_migrate/46e44de3f4a78b0773615761e783a93b.gif)
![c1361540bbeea99ac756fdb283f99f5c.png](https://i-blog.csdnimg.cn/blog_migrate/66ba087543ef7af835f8744788c7de88.png)
![11f4e5ee02f41ed445adcab0ec2a48f5.gif](https://i-blog.csdnimg.cn/blog_migrate/46e44de3f4a78b0773615761e783a93b.gif)
二叉搜索树的删除操作是二叉搜索树的最难的一点,我们不仅需要找到待删除的节点,还需要考虑删除之后如何维持树的全序性。首先分情况讨论:
删除叶结点
直接删除不会影响树的全序性,不需考虑其他问题
删除有一个儿子的结点
将以该儿子为根的子树直接连接到删除节点的父节点上,且相对位置不变(设删除节点的父节点为g,删除节点为p,其儿子节点为s,若p为g的左儿子,则s接替p为g的左儿子,右儿子情况一样)
删除有两个儿子的结点,这种情况不能像情况2一样直接拿儿子来接班,因为有左右两个子树。因此我们需要找到一个节点来替代删除节点,维护树的全序性。接班的节点必须和待删除节点一样满足大于左子树,小于右子树。因此接班节点有两种选择
左子树中的最大节点
右子树中的最小节点
![11f4e5ee02f41ed445adcab0ec2a48f5.gif](https://i-blog.csdnimg.cn/blog_migrate/46e44de3f4a78b0773615761e783a93b.gif)
![6719962759dd69247fcfa7cf43014752.png](https://i-blog.csdnimg.cn/blog_migrate/e6e0ed6c6e2acec86d12e96102bab697.png)
![8c427df188400bf009d6c198c55fd438.png](https://i-blog.csdnimg.cn/blog_migrate/6c6ea8a1817d74d235470e0646fbf040.png)
![11f4e5ee02f41ed445adcab0ec2a48f5.gif](https://i-blog.csdnimg.cn/blog_migrate/46e44de3f4a78b0773615761e783a93b.gif)
下面讲一下二叉搜索树的性质:
二叉搜索树的中序遍历是非降序的(在本文中是升序的因为节点不可重复),证明很简单,因为中序遍历的顺序是左根右。
由性质1可以推出,具有n个不同节点的二叉搜索树异构的数目满足卡特兰数(912自取)。
由2可得,n个不同节点的二叉搜索树平均搜索长度为O(√n),而并非O(logn)。O(logn)这全排列形成的二叉搜索树下统计出来的。比如n个互异节点共有n!个全排序,其中两个不同的全排列的二叉搜索树可能一样,在此情况下,同一颗树可能被统计两次,因此在无形中高估了二叉搜索树的性能。
至于插入和删除操作,在不退化时可能保证O(logn),但退化可能会导致O(n)。所以普通二叉搜索树的性能不够稳定。
![11f4e5ee02f41ed445adcab0ec2a48f5.gif](https://i-blog.csdnimg.cn/blog_migrate/46e44de3f4a78b0773615761e783a93b.gif)
![11f4e5ee02f41ed445adcab0ec2a48f5.gif](https://i-blog.csdnimg.cn/blog_migrate/46e44de3f4a78b0773615761e783a93b.gif)
下面留一道思考的题目供大家思考,我们都很熟悉二叉树的前序、中序和后序遍历,在数据结构中常提出这样的问题:已知一棵二叉树的前序和中序遍历序列,求它的后序遍历序列,相应的已知一棵二叉树的后序遍历和中序遍历序列,你也能求出它的前序遍历。然而,给定一棵二叉树的前序和后序遍历序列,你却不能确定其中序遍历序列。并且这一现象不仅出现在二叉树中,对M叉树亦如此。
若给定一个M叉树的前序和后序遍历序列,并给出M的值,求其中序遍历可能出现的数目。
例:10 abc bca 答案: 45
![11f4e5ee02f41ed445adcab0ec2a48f5.gif](https://i-blog.csdnimg.cn/blog_migrate/46e44de3f4a78b0773615761e783a93b.gif)
![11f4e5ee02f41ed445adcab0ec2a48f5.gif](https://i-blog.csdnimg.cn/blog_migrate/46e44de3f4a78b0773615761e783a93b.gif)
—— E N D ——
文字:弧度
配图:弧度