二叉搜索树的前驱和后继详细推导

后继和前驱

定义:一个结点的后继,是大于x.key的最小关键字的结点。

一个结点的前驱,是小于x.key的最大关键字的结点。

思路:找一个结点的前驱或者后继,无非是在三个区域找。

首先分析前驱:

满足两个条件,一是要小于当前键值,那么只有LP和LS区可以找。

二要求是其中最大的值。我们知道,对于LP来说,X、LS、RS都属于他的右子树,那么,X、LS和RS都是大于它的。

所以很显然,前驱就是LS中的最大值,即前驱 = 左子树中的最大值条件是:存在左子树。

那不存在左子树只有左父母的情况呢?

那只能在LP上找了,LP也具有两部分,第一部分是LP的LS,LP的LS虽然满足小于X的条件,但是LP的LS中所有元素都是小于LP的,所以至少也是LP。

还有一部分,LP可能有左父母或者右父母,显然,右父母大于他的所有左子树,包括X,条件一都不满足,显然不行。左父母小于LP,所以它竞争不过LP。

所以最终结论就是,在只有左父母,没有左子树的情况,前驱 = 左父母的值。

那不存在左子树和左父母的情况呢?

那就只剩下右子树和右父母了,显然,右子树肯定不行,它的所有元素都大于X。那就只能在右父母中找了,毕竟虽然右父母大于它,但是右父母也有左/右父母和右子树。

右父母的右父母,和右子树都不行,都大于右父母本身,更大于X了。那就只能在右父母的左父母上找了,对于左父母来说,他的右子树全都大于他,即包括X的右父母和X,所以,此时找到的左父母就是我们的前驱。

所以,不存在左子树和左父母的情况,前驱 = 右父母的左父母(如果右父母不存在左父母,就一直往上遍历,直至出现左父母)。

分析完毕。下面是代码实现。

因为我们的二叉树的结点只有Left和Right指针,所以这题感觉要用递归来做,或者栈。下面我们用栈写一个吧(时间复杂度是O(N))

BinTree Predecessor(BinTree X,BinTree BST)
{
    if(X->Left!=NULL)
        return FindMax(X->Left);
    else
    {
        Stack S;
        S = CreatStack();
        while(BST!=X)
        {
            Push(S,BST);
            if(X->Data > BST->Data)
                BST = BST->Right;
            else if(X->Data < BST->Data)
                BST = BST->Left;
        }
        BinTree Par,Son;
        Son = X;
        while((Par = Pop(S))->Right!=Son)Son = Par;//相当于Case2&3结合,直至找到左母亲为止。
        return Par;
    }
}

插播一个递归和栈的区别:

接着分析后继:(类比前驱,如果前驱看懂了可以不用看,基本上是一样的分析思路)

满足两个条件,一是要大于当前键值,那么只有RP和RS区可以找。

二要求是其中最小的值。我们知道,对于RP来说,X、LS、RS都属于他的左子树,那么,X、LS和RS都是小于它的。

所以很显然,前驱就是RS中的最小值,即后继 = 右子树中的最小值。条件是:存在右子树。

那不存在右子树只有右父母的情况呢?

那只能在RP上找了,RP也具有两部分,第一部分是LP的RS,RP的RS虽然满足大于X的条件,但是RP的RS中所有元素都是大于LP的,所以找后继,至少也得是RP。

还有一部分,RP可能有左父母或者右父母,显然,左父母小于他的所有右子树,包括X,条件一都不满足,显然不行。右父母大于RP,所以它竞争不过RP。

所以最终结论就是,在只有右父母,没有右子树的情况,后继 = 右父母的值。

那不存在右子树和右父母的情况呢?

那就只剩下左子树和左父母了,显然,左子树肯定不行,它的所有元素都小于X。那就只能在左父母中找了,毕竟虽然左父母小于它,但是右父母也有它本身的左/右父母和左子树。

左父母的左父母,和左子树都不行,都小于左父母本身,更小于X了。那就只能在左父母的右父母上找了,对于它的右父母来说,他的左子树全都小于他,即包括X的左父母和X,所以,此时找到的右父母就是我们的后继。

所以,不存在右子树和右父母的情况,后继 = 左父母的右父母(如果左父母不存在右父母,就一直往上遍历,直至出现右父母)。

分析完毕。下面是代码实现,同样是用栈实现。

BinTree Successor(BinTree X,BinTree BST)
{
    if(X->Right)
        return FindMin(X->Right);
    else
    {
        Stack S;
        S = CreatStack();
        while(BST!=X)
        {
            Push(S,BST);
            if(X->Data > BST->Data)
                BST = BST->Right;
            else if(X->Data < BST->Data)
                BST = BST->Left;
        }
        BinTree Par,Son;
        Son = X;
        while((Par = Pop(S))->Left!=Son )Son = Par;
        return Par;
    }
}

基本上是一样的。

原文地址:https://www.cnblogs.com/jasontodd/p/9613836.html

时间: 2024-11-05 16:08:37

二叉搜索树的前驱和后继详细推导的相关文章

二叉搜索树找前驱和后继

输入N个数,找每个数的前驱和后继.如果没有前驱或后继,输出-1: 思路: 如果有右子树,则右子树的最小值为当前节点的后继:否则后继为当前节点往祖先搜索,第一次是左孩子的节点的父亲的值: 如果有左子树,则左子树的最大值为当前节点的前驱:否则前驱为当前节点往祖先搜索,第一次是右孩子的节点的父亲的值: #include "bits/stdc++.h" using namespace std; typedef long long LL; const int INF = 0x3f3f3f3f;

求二叉搜索树的前驱节点和后继节点

前驱结点:节点val值小于该节点val值并且值最大的节点 后继节点:节点val值大于该节点val值并且值最小的节点 二叉树的节点val值是按照二叉树中序遍历顺序连续设定. 前驱结点 如图4的前驱结点是3 2的前驱结点是1 6的前驱结点是5 后继节点 7的后继结点是8 5的后继节点是6 2的后继节点是3 前驱节点 若一个节点有左子树,那么该节点的前驱节点是其左子树中val值最大的节点(也就是左子树中所谓的rightMostNode) 若一个节点没有左子树,那么判断该节点和其父节点的关系 2.1 若

C++实现二叉搜索树的常用操作

实现操作 (1)二叉搜索树的建立 (2)二叉搜索树的插入 (3)二叉搜索树的三种递归遍历(前序.中序和后续) (4)二叉搜索树的三种非递归遍历(前序.中序和后续) (5)二叉搜索树的逐层打印 (6)搜索某一个字符(递归算法) (7)搜索一个字符(非递归算法) (8)查找最大元素 (9)查找最小元素 有时间再实现: (10)二叉搜索树的前驱和后继查找 (11)二叉搜索树的删除 源码分析: #include <iostream> #include <stack> #include &l

二叉搜索树JavaScript实现

* 什么是二叉搜索树?其形式就是二叉树,对于每个节点x,其左子树的值<=x.value,右子树的值>=x.value. * 对于二叉搜索树,我们可以使用中序遍历,得到树上从小到大所有的元素.时间复杂度平均为O(n). function inorderTreeWalk(x) { if(x!== null) { inorderTreeWalk(x.left); print(x.key); inorderTreeWalk(x.right); } } * 当我们想要查询二叉搜索树中某个关键字应该怎么做

二叉树、二叉搜索树、AVL树的java实现

数据结构一直都是断断续续的看,总是觉得理解的不够深入,特别是对树的理解,一直都很浅显,今儿又看了一遍,来做个总结吧. 首先,树中的一些概念: 1.树的节点包含一个数据元素,以及若干指向其子树的分支.节点拥有的子树的数量称为节点的度.节点的最大层次称为树的深度或高度. 2.二叉树是一种树形结构,其特点是每个节点至多有两棵子树,且子树有左右之分,次序不能随意颠倒. 3.满二叉树:一棵深度为k且有2^k - 1个节点的二叉树,称之为满二叉树. 4.完全二叉树:对一个深度为k,节点个数为n的二叉树,当且

二叉搜索树建立、插入、删除、前继节点、后继节点之c++实现

一.前言 一直以来,都对树有关的东西望而却步.以前每次说要看一看,都因为惰性,时间就那么荒废掉了.今天下个决心,决定好好的数据结构中的东西看一下.不知道看这篇文章的你,是不是和我有同样的感受,空有一颗努力的心,却迟迟没有付出行动.如果是的话,如果也想好好的把树的知识巩固一下的话,就让我们一起好好儿地把知识点过一遍吧.本文争取让看完的每一个没有基础的同学,都能有所收获.在正文开始前,先给自己加个油.加油(^ω^) 二.二叉搜索树的定义 二叉搜索树是指,对于某一个节点而言,它左边的节点都小于或等于它

算法导论第十二章 二叉搜索树

一.二叉搜索树概览 二叉搜索树(又名二叉查找树.二叉排序树)是一种可提供良好搜寻效率的树形结构,支持动态集合操作,所谓动态集合操作,就是Search.Maximum.Minimum.Insert.Delete等操作,二叉搜索树可以保证这些操作在对数时间内完成.当然,在最坏情况下,即所有节点形成一种链式树结构,则需要O(n)时间.这就说明,针对这些动态集合操作,二叉搜索树还有改进的空间,即确保最坏情况下所有操作在对数时间内完成.这样的改进结构有AVL(Adelson-Velskii-Landis)

二叉搜索树的Java实现

为了更加深入了解二叉搜索树,博主自己用Java写了个二叉搜索树,有兴趣的同学可以一起探讨探讨. 首先,二叉搜索树是啥?它有什么用呢? 二叉搜索树, 也称二叉排序树,它的每个节点的数据结构为1个父节点指针,1个左孩子指针,1个有孩子指针,还有就是自己的数据部分了,因为只有左右两孩子,所以才叫二叉树,在此基础上,该二叉树还满足另外一个条件:每个结点的左孩子都不大于该结点&&每个结点的右孩子都大于该结点.这样,我们队这棵树进行中序遍历,就能把key从小到大排序了…… 那么问题来了,我都有线性表有

二叉树--二叉搜索树

一直对AVL这个英文缩写比较困惑,原来一直以为是平衡二叉树的首字母缩写,但是又想不明白,哈!前段时间才明白原来是种这课树的三个人的名字的首字母的,哎,生活处处有惊喜,无知不可怕,现在我也知道了.废话不多说,下面我们说说,树形结构中的那些平衡二叉树. 二叉排序树 树的遍历顺序有3种,二叉排序树,顾名思义,就是一颗有序的二叉树,是一种按照中序遍历树中节点,而输出有序队列的一种树形结构,一种特殊的树形结构. 定义 对于二叉树,假设x为二叉树中的任意一个结点,x节点包含关键字key,节点x的key值记为