二叉排序树又称二叉搜索树。
什么是二叉排序树?
定义 :
二叉排序树要么是一颗空树,要么具有以下性质:
- 若左子树不空,左子树上的节点的值小于或等于根节点的值;
- 若右子树不空,左子树上的节点的值大于或等于根节点的值;
- 左右子树也均为二叉排序树。
二叉排序树的结点类型如下
typedef struct node
{ keyType key; //关键字项
infoType data; //其他数据域
struct node *lchild, *rlchild;
} BSTNode;
1.二叉排序树上的查找
二叉排序树可看做是一个有序表,所以在二叉排序树上进行查找,和二分查找类似,也是一个逐步缩小查找范围的过程。
每一层只和一个结点进行关键字比较!
递归查找算法SearchBST()如下
BSTNode *SearchBST(BSTNoden *bt, KeyType k)
{
if(bt == NULL || bt->key == k)
return bt;
if(k<bt->key)
return SearchBST(bt -> lchild, k);
else
return SearchBST(bt -> rchild, k);
}
平衡二叉排序树
左右子树高度插值不大于1的二叉排序树
可以通过“旋转”来获得平衡二叉排序树
若在2的20次方个元素中查找某一个元素
其 2的20次方约等于10的6次方
将这些元素放入二叉排序树中,树的高度为20
则最多只需要查找20次
对于高度为n的平衡二叉排序树来说
平均查找次数为log2的n
2.二叉排序树的插入和生成
插入过程:
- 1 若二排序叉树T为空,则创建一个key域为k的结点,将它作为根结点;
- 2 否则将k和根结点的关键字比较,若两者相等,则说明树中已有此关键字k,无需插入,直接返回0;
- 3 若k< t ->key, 则将k插入根节点的左子树中。
- 4 否则将它插入右子树中。
对应的递归算法Insert BST()如下:
int InsertBST(BSTNode *&p, KeyType k)
{
if(p == NULL)
{ p=(BSTNode *)malloc(sizeof(BSTNode));
p->key = k; p->lchild = p->rchild = NULL;
return 1;
}
else if(k == p->key)
return 0;
else if(k<p->key)
return InsertBST(p->lchilde, k);
else
return InsertBST(p->rchilde, k);
}
3.二叉排序树的建立
利用二叉排序树的插入和生成实现。
BSTNode *CreatBST(KeyType A[],int n)
{ BSTNode *bt = NULL; //初始是bt为空树
int i = 0;
while(i<n)
{InsertBST(bt,A[i]); //将A[i]插入二叉排序树T中中
i++;
}
return bt;
}
T = O(n logn)
4.二叉排序树的结点删除
- 1 被删结点是叶子节点:直接删除,并将其双亲节点中相应的指针域的值改为空
- 2 被删除的结点只有左子树或者右子树,用其左子树或者右子树替换它。
- 3 被删结点有左子树也有右子树,用其中序前驱值替换,然后再删除该前趋结点。前趋是左子树中最大的结点。
5.如何判断两个二叉排序树是否相等?
不能只用中序遍历来判断,不同二叉排序树可能会出现中序相等的情况,如上图。
需要中序遍历和前序遍历来共同判断。
【附加】数组去重
int a[n] = {…};
(1) sort
1, 2, 2, 3, 3, 4 利用双指针i, j
(2) 哈希 STL: map[a[i]]++
map[i]++; //多余的计入,不再放到二叉排序树里(二叉排序树中无重复元素)
map类->底层->红黑树->变形的二叉排序树