Fork me on GitHub

二叉搜索树

--------------------siwuxie095

   

   

   

   

   

   

   

   

二叉搜索树

   

   

这里介绍二叉搜索树(Binary Search Tree)

   

二叉搜索树,顾名思义,本质上也是一棵二叉树

   

   

   

二叉树在计算机中是一种非常常用的数据结构,选择什么类型的二叉树

很多时候要根据需要解决的问题而定

   

使用数据结构的核心是要解决问题,而并非是为了使用数据结构而使用

数据结构

   

使用二叉树并不是因为二叉树很酷,很炫,听起来很专业,而是因为二

叉树能够高效的解决一类问题

   

   

   

二叉搜索树解决的一类问题就是在计算机中非常常见的查找问题

   

「查找问题是计算机中非常重要的基础问题」

   

可能很多人会觉得这个问题非常简单,就是在一组数据中找到某

个数据,但是仔细想一想就会发现,查找问题虽然描述出来很简

单,但是它的应用却非常广泛

   

从去银行办理业务时,银行根据证件号码从系统中调出相应的信

息,到在 Google 中搜索内容时,Google 根据关键字来查找相

关的信息

   

查找问题,是一个听起来非常朴素,实际上却非常困难,被研究

的非常广泛的一类问题

   

「查找问题,即 Search Problem」

   

   

   

   

   

   

   

二叉搜索树的优势

   

   

事实上,二叉搜索树,通常都用于实现 查找表

   

有的地方,也称 查找表 字典,如下:

   

key1

value1

key2

value2

key3

value3

key4

value4

key5

value5

   

对于这些数据而言,都是一个一个键值对,即 key-value

对应的数据对,给你一个 key,相应的就有一个 value

   

这样大量的数据对,集合在一起就形成了一张表,在这张表

中通过键(key)就能直接查到对应的值(value)

   

   

   

最典型的一个应用就是字典。对于一个字典来说,键(key)

就是一个个单词,而值(value)就是单词的释义

   

这也是查找表有时候也被称为字典这样一种数据结构的原因

   

   

   

如果这些 key 都是整数,而且范围比较小,那么使用数组就可以轻易

地用索引直接来索引到相应的 value

   

但在实际的业务逻辑中,很多时候不能用整数来表达这样的键(key),

或者是因为这些键(key)相对比较稀疏,使用数组在空间上并不经济,

或者是因为这些键(key)压根就不能用整数来表示

   

例如:字典的键(key)其实是一个字符串

   

这种情况下,就需要实现一个查找表,而实现查找表的最基础的一个

方式是实现二叉搜索树

   

当然,也完全可以用 普通数组 顺序数组 来实现这个一个查找表

   

  

查找元素

插入元素

删除元素

普通数组

O(n)

O(n)

O(n)

顺序数组

O(lgn)

O(n)

O(n)

二分搜索树

O(lgn)

O(lgn)

O(lgn)

   

   

可以简单分析一下使用普通数组 顺序数组的时间效率:

   

1)使用普通数组

   

查找一个元素,就需要使用 O(n) 的时间从头到尾遍历一遍,看要找的

那个元素在数组的什么位置

   

插入一个元素,也需要使用 O(n) 的时间从头到尾遍历一遍,因为对于

查找表来说,需要先看一看当前查找表中是否已经含有要插入的元素。

如果没有,再插入;如果有的话,就应该是对 key 相应的 value 进行

一个更新操作

   

删除一个元素,也需要使用 O(n) 的时间从头到尾遍历一遍,来删除相

应的元素

   

   

2)使用顺序数组

   

要一直保证这个数组是有序的。这样一来,查找一个元素就可以使用

二分查找法,用 O(lgn) 的时间进行查找,但对于插入一个元素和删除

一个元素来说,依然要使用 O(n) 的时间

   

   

   

相较而言,二叉搜索树就高效很多,它能够保证查找、插入、删除这

三个操作的时间复杂度近乎都是 O(lgn) 级别的

   

   

   

所以,二叉搜索树的优势:

   

1)高效

   

不仅可以高效查找数据,还可以高效地插入数据、删除数据 - 动态维护数据

   

也就是说,如果能一下就把所有的数据拿到手,那可能先对数据进行排序再

使用二分查找法,就足够了

   

但在很多时候,查找、插入、删除这三个操作,在业务的过程中都是要涉及

的,因此,二叉搜索树提供了一个可以非常高效地动态维护数据的方式

   

   

2)可以方便地回答很多数据之间的关系问题,如下:

   

minmaxfloorceilrankselect

   

可以轻易地找到所有数据中的最小值 min、最大值 max,某个数据的 floor

相应的值、ceil 相应的值,还有给定一个数据,求它的排名 rank,以及找

到所有数据中某排名(如:第 100 名)的数据 select

   

   

   

   

   

   

   

二叉搜索树的定义

   

   

如下图所示,是一棵二叉搜索树:

   

   

   

二叉搜索树,是指一棵空树 或者具有下列性质的二叉树:

   

1)若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值

2)若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值

3)任意节点的左、右子树也分别为二叉搜索树

4)没有键值相等的节点

   

   

   

   

1)每个节点的键值都大于左孩子

2)每个节点的键值都小于右孩子

   

   

   

不难看出,二叉搜索树的定义中天然就包含了递归结构

   

正因为如此,在对二叉搜索树编程时,很多时候都可以使用递归函数的方式,

方便快速地实现很多功能

   

   

   

注意:对于堆来说,堆的那棵二叉树一定是一棵完全二叉树,但对于二叉搜索

树来说,是没有这个限制的,如下:

   

   

   

换句话说,上图中的这棵树,也是二叉搜索树,即 二叉搜索树,不一定是

完全二叉树

   

在实现堆的时候,是利用了堆一定是一棵完全叉树的特点,所以能用数组

来表示堆,但二分搜索树不一定是完全二叉树,所以用数组表示并不方便

   

因此,通常是设立 Node 节点,来表示 key-value 这样的数据对,而节点

之间的联系,则使用指针的方式来表示

   

   

   

   

   

   

   

   

   

【made by siwuxie095】

posted on 2017-06-09 23:52  siwuxie095  阅读(194)  评论(0编辑  收藏  举报

导航