之前提到的斐波那契查找、二分查找和插值查找都是基于有序的线性表存储结构,称为静态查找表,它们在查找表需要频繁插入和删除的操作的情况下不适用,那有没有即可以使得插入和删除效率不错,又可以比较高效率地实现查找的算法呢?这种需要在查找时插入或删除的查找表称为动态查找表。
1、二叉查找树
二分查找的过程既然能用二叉树进行表示,说明该逻辑可以使用二叉树进行实现,使用二分查找思想实现的二叉树就称为二叉查找树。
二叉排序树(Binary Sort Tree,简称BST),又称为二叉查找树。它要么是一棵空树,要么是具有下列性质的二叉树:
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 它的左、右子树也分别为一颗二叉排序树;
1.1、二叉查找树的插入
若我们现在需要对数据集:{62, 88, 58, 47, 35, 73, 51, 99, 37, 93}进行查找,我们可以选择使用二叉查找树来实现。
首先我们需要定义二叉树的结构,与普通二叉树一样:
typedef int DataType; /*树结点的数据元素类型*/
typedef struct BinaryNode { /*二叉树结点结构*/
DataType data; /*数据域*/
BinaryNode *leftChild; /*左孩子*/
BinaryNode *rightChild; /*右孩子*/
}*BinaryTree;
接着我们需要根据数据集构造一颗二叉查找树,就是将数据集中的数据挨个插入:
- 第一个数62,此时二叉树为空则62作为根结点;
- 下一个数88比62大,所以作为62的右孩子结点(见①);
- 下一个数58比62小,所以作为62的左孩子结点(见②);
- 下一个数47比62小,也比58小,所以作为58的左孩子结点(见③);
- 下一个数35比62小,也比58小,也比47小,所以作为47的左孩子结点(见④);
- 下一个数73比62大,但比88小,所以作为88的左孩子结点(见⑤);
- 下一个数51比62小,也比58小,但比47大,所以作为47的右孩子结点(见⑥);
- 下一个数99比62大,也比88大,所以作为88的右孩子结点(见⑦);
- 下一个数37比62小,也比58小,也比47小,但比35大,所以作为35的右孩子结点(见⑧);
- 下一个数93比62大,也比88大,但比99小,所以作为99的左孩子结点(见⑨);