由于这部分是以前看多的,就直接贴书上的图了。。。
1. 二叉查找树的定义
2. 二叉查找树的基本操作——“增删改查建”
二叉查找树的基本操作有查找、插入、建树、删除。
2.1 查找操作
采用递归实现查找操作。
//search函数查找二叉查找树种数据域为x的结点
void search(node* root,int x){
if(root == NULL){
printf("search failed\n");
return;
}
if(x == root->data){
printf("%d\n",root->data);
}else if(x < root->data){
search(root->lchild,x);
}else{
search(root->rchild,x);
}
}
与普通的二叉树的查找函数不同,二叉查找树的查找在于对左右子树的选择递归。
2.2 插入操作
- 插入操作是基于查找操作的。
- 注意传地址。
//insert函数将在二叉树中插入一个数据域为x的新结点(注意参数root要加&)
void insert(node* &root,int x){
if(root == NULL){
root = newNode(x);
return;
}
if(x == root->data){
return;
}else if(x < root->data){
insert(root->lchild,x);
}else{
insert(root->rchild,x);
}
}
2.3 建树操作
//二叉查找树的建立
node* Create(int data[],int n){
node* root = NULL;
for(int i=0;i<n;i++){
insert(root,data[i]);
}
return root;
}
注意:
- 一棵二叉查找树的先序遍历得到的序列可以用来重新构建出这棵二叉查找树!!! ⭐⭐⭐⭐⭐ ‘
由于二叉树的性质,所以我们可以确定左右子树,所以不需要中序遍历就能重构二叉查找树。
2.4 删除操作
采用递归实现删除操作。
- 寻找以root为根结点的树中的最大权值结点
- 寻找以root为根结点的树中的最小权值结点
//寻找以root为根结点的树中的最大权值结点
node* findMax(node* root){
while(root->rchild != NULL){
root = root->rchild;
}
return root;
}
//寻找以root为根结点的树中的最小权值结点
node* findMin(node* root){
while(root->lchild != NULL){
root = root->lchild;
}
return root;
}
注意,删除操作也是使用递归的方式写的。
注意:在下面描述的 x
是待删除的结点的值。删除操作把 查找元素 x
和 删除元素x
结合在了一起。
//删除以root为根结点的树中权值为x的结点
void deleteNode(node* &root,int x){
if(root == NULL)
return; //不存在权值为x的结点
if(root->data == x){ //找到欲删除结点
if(root->lchild == NULL && root->rchild == NULL){
root = NULL;
}else if(root->lchild != NULL){
node* pre = findMax(root->lchild);
root->data = pre->data;
deleteNode(root->lchild,pre->data);
}else{
node* next = findMin(root->rchild);
root->data = next->data;
deleteNode(root->rchild,next->data);
}
}else if(root->data > x){
deleteNode(root->lchild,x);
}else{
deleteNode(root->rchild,x);
}
}
优化
3. 二叉查找树的性质⭐⭐⭐⭐⭐
-
通过使用本节中定义的构树函数
create()
读入一棵二叉查找树的先序遍历得到的序列可以用来重新构建出这棵二叉查找树!!! ⭐⭐⭐⭐⭐ (不要傻乎乎的去使用传统先序+中序的方法)
参考例题是这道——⭐PAT A1135 Is It A Red-Black Tree
然而事实证明,如果建树的过程是一个一个insert()
进行的,这种建树方法称为 在线建树 ,而如果直接使用前序序列一次性进行建树,则成为 离线建树 ,由于在线建树每次都会有大量的重复的查找操作,因此时间复杂度非常高,最坏为 O ( N 2 ) O(N^2) O(N2)!而离线建树的时间复杂度为 O ( N ) O(N) O(N),因此,以后还是使用离线建树比较好!即还是使用传统先序+中序的方法更好!!!
参考例题是这道——⭐⭐⭐⭐⭐PAT A1143 Lowest Common Ancestor -
中序遍历得到有序结果
4. 题型训练
- 【PAT A1043】Is It a Binary Search Tree
- 【PAT A1064】Complete Binary Search Tree
- 【PAT A1099】Build A Binary Search Tree
- ⭐二叉搜索树——浙大10年(错题)
- 二叉排序树——华科05年
- 二叉排序树02——华科
- LeetCode 230. Kth Smallest Element in a BST
- 删除结点——LeetCode 450. Delete Node in a BST
- 二分与二分查找树——LeetCode 109. Convert Sorted List to Binary Search Tree
- PAT A1115 Counting Nodes in a BST
- ⭐PAT A1135 Is It A Red-Black Tree
- ⭐⭐⭐⭐⭐PAT A1143 Lowest Common Ancestor