二叉查找树 (binary search tree) 是具有下列性质的二叉树:(1) 若它的左子树不空,则左子树上所有结点的值均小于根结点的值;(2) 若它的右子树不空,则右子树上所有结点的值均大于根结点的值;(3) 它的左右子树也都是二叉排序树。
在二叉查找树上进行查找,与待查值比较后,根据比较结果只需要查找两个子树之一,因此,二叉查找树也是减治技术的成功应用。
【问题】在一个无序序列中执行查找操作,可以将无序序列建立一棵二叉查找树,然后在二叉查找树中查找值为k的记录,若查找成功,返回记录 k 的存储地址,若查找失败,返回空指针。
【想法】由二叉查找树的定义,在二叉查找树 root 中查找给定值 k 的过程如下。
(1) 若 root 是空树,则查找失败;
(2) 若 k = 根结点的值,则查找成功;
(3) 若 k < 根结点的值,则在root的左子树上查找;
(4) 若 k > 根结点的值,则在root的右子树上查找。
上述过程一直持续到查找成功或者待查找的子树为空,如果待查找的子树为空,则查找失败。例如,在下图所示的二叉查找树上查找记录 58,首先将 58 与根结点比较,因为 58<63,则在以 63为根结点的左子树上查找,63 的左子树不空,则将 58 与其根结点 55 比较,因为 58>55,则在以 55 为根结点的右子树上查找,55 的右子树不空,且 58 与其根结点相等,则查找成功。和上述过程类似,查找记录 95,在 95 同 63、90 比较后,因为 90<95,则在以 90 为根结点的右子树上查找,但该子树为空,故查找失败。
【算法分析】在二叉查找树上查找值为 k 的记录结点的过程,恰好走了一条从根结点到该结点的路径,和待查值的比较次数等于该结点在二叉查找树中的层数,比较次数最少为 1 次(即整个二叉查找树的根结点就是待查结点),最多不超过树的深度。具有 n 个结点的二叉树的深度至少是 [] +1,至多是 n,所以,二叉查找树的查找性能在O() 和 O(n) 之间。
【算法实现】二叉查找树的查找算法用JAVA语言描述如下:
public class BiNode {
int data; //结点的值,假设查找集合的元素为整型
BiNode lchild, rchild; //指向左、右子树的指针
public static void main(String[] args)
{
BiNode root, t;
int a[]={55,42,10,70,63,58,83,67,90,45};
root=createBST(a,10);
t=SearchBST(root,58);
if(t != null)
System.out.println("查找成功");
else
System.out.println("查找失败");
}
static BiNode insertBST(BiNode root, int data)
{
if(root == null)
{
root = new BiNode();
root.data = data;
root.lchild = null;
root.rchild = null;
return root;
}
if(data <= root.data)
root.lchild = insertBST(root.lchild, data);
else
root.rchild = insertBST(root.rchild, data);
return root;
}
static BiNode createBST(int a[], int n)
{
BiNode T = null;
for (int i=0; i < n; i++)
T = insertBST(T, a[i]);
return T;
}
static BiNode SearchBST(BiNode root, int k)
{
if (root == null) return null; //二叉查找树为空,查找失败
else if (root.data == k) return root; //查找成功
else if (k < root.data) //查找左子树
return SearchBST(root.lchild, k);
else //查找右子树
return SearchBST(root.rchild, k);
}
}
运行结果如下:
from:算法设计与分析(第2版)——王红梅 胡明 编著——清华大学出版社