C++深入细致探究二叉搜索树

目录
  • 1、二叉搜索树的概念
  • 2、二叉搜索树的操作
    • 二叉搜索树的查找
    • 二叉搜索树的插入
    • 二叉搜索树的删除
  • 3、二叉搜索树的实现
  • 4、二叉搜索树的性能分析

1、二叉搜索树的概念

 二叉搜索树又称二叉排序树,它可以是一颗空树,亦可以是一颗具有如下性质的二叉树:

  ①若根节点的左子树不为空,则左子树上的所有节点的值域都小于根节点的值

  ②若根节点的右子树不为空,则右子树上的所有节点的值域都大于根节点的值

  ③根节点的左右子树分别也是一颗二叉搜索树

例如下面的这棵二叉树就是一棵二叉搜索树:

注意:判定一棵二叉树是否为二叉搜索树一定要紧扣二叉搜索树的概念~

2、二叉搜索树的操作

声明:该文章讨论的是二叉搜索树中节点值唯一的情况。

二叉搜索树的查找

对于查找部分,充分利用二叉搜索树的特性,即右子树的value 大于根节点,左子树的value小于根节点。

例如:查找下图中的红色方框中的节点

以6对应的节点为列,查找过程主要经历如下几个步骤:

  ①6与根节点5比较,6 > 5,因此到5的右子树查找

  ①6与根节点7比较,6 < 7,因此到7的左子树查找

  ①6与根节点6比较,6 == 6,此时查找成功!

总结基本步骤:

若根节点不为空:

  如果根节点的key == 查找的key----->返回true

  如果根节点的key > 查找的key----->转到根节点的右子树查找

  如果根节点的key < 查找的key----->转到根节点的左子树查找

否则(根节点为空了),直接返回false,表示树中不存在要查找的key

二叉搜索树的插入

主要分两大类的情况进行讨论:

1、树为空,直接插入

如下图所示:

2、树不空

①按照二叉搜索树的性质查找插入的位置

②插入新的节点

e.g:在下面的二叉搜索树中插入-1

第一步,查找插入位置:

 注意:要标记当前访问的节点的双亲,否则,就算找到了插入位置,由于无法访问其双亲,也是无法进行插入的。这里使用parent来标记当前访问节点的双亲节点。

具体过程如下图:

第二步,插入新节点

判断待插入节点(node)的值与parent标记的节点值的大小关系

if(node->value < parent->value)//新节点作为parent的左孩子
{
	parent->left = node;
}
else//新节点作为parent的右孩子
{
	parent->right = node;
}

以上就是二叉搜索树插入的两大类情况及其处理方式

二叉搜索树的删除

删除也是分为两大步骤:

1、找到待删除结点,并标记其双亲

具体代码片段如下:

Node* delNode = root;//标记待删除结点
Node* parent = nullptr;//标记待删除结点的双亲
while(delNode)
{
	if(delNode->value == value)
	{
		break;
	}
	else if(delNode->value > value)
	{
		parent = delNode;
		delNode = delNode->left;
	}
	else
	{
		parent = delNode;
		delNode = delNode->right;
	}
}

上述代码执行完毕后,delNode有两种情况,delNode == nullptr || delNode!=nullptr

下面我们就这两种情况展开讨论:

2、删除该节点

Ⅰ、nullptr == delNode

  说明在二叉搜索树中不存在要删除的结点。直接return false;

Ⅱ、delNode != nullptr;

  在二叉搜索树中找到了删除结点,开始删除。

删除时,对于待删除结点要根据其孩子节点分情况讨论:

  ①待删除结点是叶子结点

  ②待删除结点只有左孩子

  ③待删除结点只有有孩子

  ④待删除结点左右孩子均存在

下面,我们就这4中情况展开讨论:

情况一:待删除结点时叶子节点

可以直接删除,具体如下图:

情况二:待删除结点只有左孩子

在此前提下,有两类情形

1、delNode的双亲存在  

2、delNode的双亲不存在

下面就这两种情况展开讨论:

1、delNode的双亲存在

删除过程见下图:

2、delNode的双亲不存在

与上述仅存在叶子节点时存在的问题一样,需要在delete待删除结点之前,判断delNode与parent的位置关系,进而确定是更新parent的left指针域还是right指针域

结合上述两种情况,初步确定仅有左孩子的删除代码片段如下:

if(nullptr == parent)
{
	root = delNode->left;
}
else
{
	if(delNode == parent->left)
	{
		parent->left = delNode->left;
	}
	else
	{
		parent->right = delNode->left;
	}
}
delete delNode;

我们结合删除节点是叶子节点 && 删除节点仅有左子树两种情况来看,发现这两种情况可以进行合并。合并后的代码如下图:

情况三:待删除结点只有右孩子

该情况与只有左孩子的分析过程一样,存在两类情形,分别是

1、delNode的双亲存在  

2、delNode的双亲不存在

这里不再进行分析,直接给出代码:

情况四:待删除结点左右孩子均存在

明确:该情况无法直接删除,需要在其子树中寻找替代结点 具体删除步骤如下:

1、找替代节点:在delNode的右子树(左子树)找最左侧(最右侧)的结点并保存其双亲

2、将替代节点中的值域赋值给待删除结点

3、将替代节点删除掉

①如果替代节点找的是delNode右子树的最左侧结点,那么待删除的替代节点一定不会有左子树,可能会有右子树

②如果替代节点找的是delNode左子树的最右侧结点,那么待删除的替代节点一定不会有右子树,可能会有左子树 注意:一般情况下采用delNode右子树的最左侧结点作为替代节点

具体过程见下图:

ok,下面给出实现的代码:

3、二叉搜索树的实现

数据结构:

template<class T>
struct BSTNode//每一个结点的结构
{
	BSTNode<T>* _left;//左指针域
	BSTNode<T>* _right;//右指针域
	T _value;//值域

	BSTNode(const T& value = T())
		:_left(nullptr)
		, _right(nullptr)
		, _value(value)
	{}
};

采用模板的方式实现,具体代码见 BinarySearchTree

4、二叉搜索树的性能分析

插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能

对于有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数。即结点越深,比较次数越多。

但对于同一个关键码的集合,如果各关键码插入的次序不同,可能会得到不同的二叉搜索树:

最优情况下:二叉搜索树为完全二叉树,其平均比较次数为log2N

最差情况下:二叉搜索树退化为单支树,其平均比较次数为N/2

因此,二叉搜索树的时间复杂度为O(log2N)

到此这篇关于C++深入细致探究二叉搜索树的文章就介绍到这了,更多相关C++二叉搜索树内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++ 二叉搜索树(BST)的实现方法

    废话不多说了,直接给大家贴代码了,具体代码如下所示: class BST { public: struct Node { int key;//节点的key int value;//节点的value Node* left; Node *right; int N;//节点的叶子节点数目 Node(int _key, int _value, int _N) { key = _key; value = _value; N = _N; } }; BST(); ~BST(); void put(int ke

  • C++数据结构二叉搜索树的实现应用与分析

    目录 概念 二叉搜索树的实现

  • C++如何将二叉搜索树转换成双向循环链表(双指针或数组)

    目录 二叉搜索树转换成双向循环链表 二叉搜索树与双向链表(C++中等区) 解题思路 代码展示 二叉搜索树转换成双向循环链表 本文解法基于性质:二叉搜索树的中序遍历为 递增序列 . 将二叉搜索树 转换成一个 “排序的循环双向链表”,其中包含三个要素: 1.排序链表:节点应从小到大排序,因此应使用 中序遍历 2.“从小到大”访问树的节点.双向链表:在构建相邻节点的引用关系时,设前驱节点 pre 和当前节点 cur , 不仅应构建 pre.right= cur,也应构建 cur.left = pre

  • C++ 超详细快速掌握二叉搜索树

    目录 二叉搜索树概念与操作 二叉搜索树的概念 二叉搜索树的操作 查找 插入 删除 二叉搜索树的应用 二叉树的性能分析 二叉搜索树概念与操作 二叉搜索树的概念 二叉搜索树又称二叉排序树,若它的左子树不为空,则左子树上所有节点的值都小于根节点的值:若它的右子树不为空,则右子树上所有节点的值都大于根节点的值,它的左右子树也分别未二叉搜索树.也可以是一颗空树. int a[] = { 5, 3, 4, 1, 7, 8, 2, 6, 0, 9 }; 二叉搜索树的操作 查找 迭代: Node* Find(c

  • C++深入细致探究二叉搜索树

    目录 1.二叉搜索树的概念 2.二叉搜索树的操作 二叉搜索树的查找 二叉搜索树的插入 二叉搜索树的删除 3.二叉搜索树的实现 4.二叉搜索树的性能分析 1.二叉搜索树的概念  二叉搜索树又称二叉排序树,它可以是一颗空树,亦可以是一颗具有如下性质的二叉树:   ①若根节点的左子树不为空,则左子树上的所有节点的值域都小于根节点的值   ②若根节点的右子树不为空,则右子树上的所有节点的值域都大于根节点的值   ③根节点的左右子树分别也是一颗二叉搜索树 例如下面的这棵二叉树就是一棵二叉搜索树: 注意:判

  • Javascript实现从小到大的数组转换成二叉搜索树

    废话不多说了,直接给大家贴代码了,具体代码如下所示: var Array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; var Tree = createTree(Array); console.log(Tree); // 构造一个节点 function Node(nodeData, leftData, rightData) { this.nodeData = nodeData; this.leftData = leftData; this.rightData = rig

  • Python二叉搜索树与双向链表转换实现方法

    本文实例讲述了Python二叉搜索树与双向链表实现方法.分享给大家供大家参考,具体如下: # encoding=utf8 ''' 题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表. 要求不能创建任何新的结点,只能调整树中结点指针的指向. ''' class BinaryTreeNode(): def __init__(self, value, left = None, right = None): self.value = value self.left = left self.

  • javascript算法之二叉搜索树的示例代码

    什么是二叉树 二叉树就是树的每个节点最多只能有两个子节点 什么是二叉搜索树 二叉搜索树在二叉树的基础上,多了一个条件,就是二叉树在插入值时,若插入值比当前节点小,就插入到左节点,否则插入到右节点:若插入过程中,左节点或右节点已经存在,那么继续按如上规则比较,直到遇到一个新的节点. 二叉搜索树的特性 二叉搜索树由于其独特的数据结构,使得其无论在增删,还是查找,时间复杂度都是O(h),h为二叉树的高度.因此二叉树应该尽量的矮,即左右节点尽量平衡. 二叉搜索树的构造 要构造二叉搜索树,首先要构造二叉树

  • javascript数据结构之二叉搜索树实现方法

    本文实例讲述了javascript二叉搜索树实现方法.分享给大家供大家参考,具体如下: 二叉搜索树:顾名思义,树上每个节点最多只有二根分叉:而且左分叉节点的值 < 右分叉节点的值 . 特点:插入节点.找最大/最小节点.节点值排序 非常方便 二叉搜索树-javascript实现 <script type="text/javascript"> // <![CDATA[ //打印输出 function println(msg) { document.write(msg

  • Python实现二叉搜索树

    二叉搜索树 我们已经知道了在一个集合中获取键值对的两种不同的方法.回忆一下这些集合是如何实现ADT(抽象数据类型)MAP的.我们讨论两种ADT MAP的实现方式,基于列表的二分查找和哈希表.在这一节中,我们将要学习二叉搜索树,这是另一种键指向值的Map集合,在这种情况下我们不用考虑元素在树中的实际位置,但要知道使用二叉树来搜索更有效率. 搜索树操作 在我们研究这种实现方式之前,让我们回顾一下ADT MAP提供的接口.我们会注意到,这种接口和Python的字典非常相似. Map() 创建了一个新的

  • 二叉搜索树的插入与删除(详细解析)

    题目:创建一个类,类中的数据成员时一棵二叉搜索树,对外提供的接口有添加结点和删除结点这两种方法.用户不关注二叉树的情况.要求我们给出这个类的结构以及实现类中的方法. 思路添加结点:添加结点其实很容易,我们只需要找到结点所行对应的位置就可以了,而且没有要求是平衡的二叉搜索树,因此每次添加结点都是在叶子结点上操作,不需要修改二叉搜索树整体的结构.要找出添加节点在二叉搜索树中的位置,可以用一个循环解决.判断插入结点与当前头结点的大小,如果大于头结点则继续搜索右子树,如果小于头结点则继续搜索左子树.直到

  • C#创建二叉搜索树的方法

    本文实例讲述了C#创建二叉搜索树的方法.分享给大家供大家参考.具体如下: public static BinaryTreeNode BuildBinarySearchTree(int[] sortedArray) { if (sortedArray.Length == 0) return null; int _mid = sortedArray.Length / 2; BinaryTreeNode _root = new BinaryTreeNode(sortedArray[_mid]); in

  • Java 实现二叉搜索树的查找、插入、删除、遍历

    由于最近想要阅读下JDK1.8 中HashMap的具体实现,但是由于HashMap的实现中用到了红黑树,所以我觉得有必要先复习下红黑树的相关知识,所以写下这篇随笔备忘,有不对的地方请指出- 学习红黑树,我觉得有必要从二叉搜索树开始学起,本篇随笔就主要介绍Java实现二叉搜索树的查找.插入.删除.遍历等内容. 二叉搜索树需满足以下四个条件: 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值: 任意节点的左.右子

随机推荐