算法设计与分析——二叉搜索树(一):基础知识

分类目录:《算法设计与分析》总目录
相关文章:
· 二叉搜索树(一):基础知识
· 二叉搜索树(二):查询二叉搜索树
· 二叉搜索树(三):插入和删除
· 二叉搜索树(四):随机构建二叉搜索树的期望高度


搜索树数据结构支持许多动态集合操作,包括查找、最大元素、最小元素、 前驱、后继、插入和删除等。因此,我们使用一棵搜索树既可以作为一个字典又可以作为一个优先队列。

二叉搜索树上的基本操作所花费的时间与这棵树的高度成正比。对于有 n n n个结点的一棵完全二叉树来说,这些操作的最坏运行时间为 Θ lg ⁡ ( n ) \Theta\lg (n) Θlg(n)。然而,如果这棵树是一条 n n n个结点组成的线性链,那么同样的操作就要花费 Θ ( n ) \Theta(n) Θ(n)的最坏运行时间。后续的文章中,我们将看到一棵随机构造的二叉搜索树的期望高度为 O ( lg ⁡ n ) O(\lg n) O(lgn),因此这样一棵树上的动态集合的基本操作的平均运行时间是 Θ ( lg ⁡ n ) \Theta(\lg n) Θ(lgn)

实际上,我们并不能总是保证随机地构造二叉搜索树,然而可以设计二叉搜索树的变体,来保证基本操作具有好的最坏情况性能。后续的文章还会给出了一个这样的变形,即红黑树,它的树高为 O ( lg ⁡ n ) O(\lg n) O(lgn)。除此之外,我们也会介绍B树,它特别适用于二级(磁盘)存储器上的数据库维护。

在给出二叉搜索树的基本性质之后,我们将在《算法设计与分析——二叉搜索树》整个系列中完整地介绍如何遍历一棵二叉搜索树来按序输出各个值,如何在一棵二叉搜索树上查找一个值,如何查找最小或最大元素,如何查找一个元素的前驱和后继,以及如何对一棵二叉搜索树进行插入和删除。

顾名思义,一棵二叉搜索树是以一棵二叉树来组织的,如下图所示。这样一棵树可以使用一个链表数据结构来表示,其中每个结点就是一个对象。除了 k e y key key和卫星数据之外,每个结点还包含属性 l e f t left left r i g h t right right p p p,它们分别指向结点的左孩子、右孩子和双亲。如果某个孩子结点和父结点不存在,则相应属性的值为 N o n e None None。根结点是树中唯一父指针为 N o n e None None的结点。

class BSTNode():
    def __init__(self, key, value, left=None, right=None):
        self.key = key
        self.value = value
        self.left = left
        self.right = right

二叉搜索树中的关键字总是以满足二叉搜索树性质的方式来存储:
x x x是二叉搜索树中的一个结点。如果 y y y x x x左子树中的一个结点,那么 y . k e y ≤ x . k e y y.key\leq x.key y.keyx.key。如果 y y y x x x右子树中的一个结点,那么 y . k e y ≥ x . k e y y.key \geq x.key y.keyx.key
搜索二叉树
因此,在上左图中,树根的关键字为6,在其左子树中有关键字2、5和5,它们均不大于6;而在其右子树中有关键字7和8,它们均不小于6。这个性质对树中的每个结点都成立。例如,树根的左孩子为关键字5,不小于其左子树中的关键字2并且不大于其右子树中的关键字5。

二叉搜索树性质允许我们通过一个简单的递归算法来按序输出二叉搜索树中的所有关键字,这种算法称为中序遍历算法。这样命名的原因是输出的子树根的关键字位于其左子树的关键字值和右子树的关键字值之间。类似地,先序遍历中输出的根的关键字在其左右子树的关键字值之前,而后序遍历输出的根的关键字在其左右子树的关键字值之后。调用下面的过程 INORDER-TREE-WALK( T. root),就可以输出一棵二叉搜索树T中的所有元素。

def inorder_tree_walk(x):
    if x != None:
        inorder_tree_walk(x.left)
        print(x.key)
        inorder_tree_walk(x.right)

遍历一棵有 n n n个结点的二叉搜索树需要耗费 Θ ( n ) \Theta(n) Θ(n)的时间,因为初次调用之后,对于树中的每个结点这个过程恰好要自己调用两次:一次是它的左孩子,另一次是它的右孩子。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

von Neumann

您的赞赏是我创作最大的动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值