目录
转自:https://blog.csdn.net/haofight/article/details/54381804
一、二叉查找树的概念
二叉查找树(Binary Search Tree),又被称为二叉搜索树。
它是特殊的二叉树:对于二叉树,假设x为二叉树中的任意一个结点,x节点包含关键字key,节点x的key值记为key[x]。如果y是x的左子树中的一个结点,则key[y] <= key[x];如果y是x的右子树的一个结点,则key[y] >= key[x]。那么,这棵树就是二叉查找树。如下图所示:
在二叉查找树中:
(1) 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2) 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3) 任意节点的左、右子树也分别为二叉查找树。
(4) 没有键值相等的节点(no duplicate nodes)。
二、二叉查找树的实现
1、节点定义
typedef int Elemtype;
typedef struct BSTNode
{
Elemtype data;
struct BSTNode *lchild,*rchild;
}BSTNode,*PNode;
2、建树(即插入节点)
//向树中插入节点,若此节点在不在树中则插入,已在树中则不插入
PNode insertBST(Elemtype data,PNode root)
{
if(root==NULL)
{
PNode root=new BSTNode();
root->data=data;
root->lchild=NULL;
root->rchild=NULL;
return root;
}
if(data<root->data)
root->lchild=insertBST(data,root->lchild);
else if(data>root->data)
root->rchild=insertBST(data,root->rchild);
return root;
}
3、在树中查找某个节点
根据二叉查找树的性质,只需判断查找值与节点的大小关系,若比节点小则递归左子树,反之递归右子树。
//查找结点,树中存在结点值为data的结点返回true,否则返回false
bool SearchBST(PNode T,Elemtype data)
{
if(T==NULL)
return false;
if(data<T->data)
return SearchBST(T->lchild,data);
else if(data>T->data)
return SearchBST(T->rchild,data);
else
return true;
}
4、查找该树的最大值、最小值
最小值采用递归实现,最大值采用非递归实现,根据二叉查找树的性质,最小值为左子树的最左节点,最大值为右子树的最右节点。
//查找二叉查找树中最大、最小节点值;从根节点开始查找左儿子,
//只要存在左儿子就一直查找,终点就是最小的元素,最大的为右儿子查找终点
PNode findMin(PNode root)
{
if(root==NULL)
return NULL;
else if(root->lchild==NULL)
return root;
return findMin(root->lchild); //递归查找
}
PNode findMax(PNode root)
{
if(root!=NULL) //非递归查找
while(root->rchild!=NULL)
root=root->rchild;
return root;
}
5、删除节点
稍微有些复杂,需要分3种情况分别讨论。
(1)需要删除的是叶节点(没有子节点的节点),直接把节点删除即可。
(2)需要删除的是链节点(只有一个子节点的节点),为了删除这个节点而不影响它的子树,需要用它的子节点代替它的位置,然后把它删除。
(3)需要删除的节点由两个非空子节点。由于情况比较复杂,一般用它右子树的最小值来代替它,然后把它删除。
//删除一个结点:如果是叶结点则直接删除;
//如果结点有一个孩子,则直接用该结点父节点连接此结点孩子结点,删除此节点;
//如果结点有两个孩子结点,则用其右子树的最小数据代替该结点的数据并递归的删除那个最小结点,因为右子树的
//最小结点不可能有左儿子因此第二次删除比较容易
PNode deleteBST(PNode root,Elemtype data)
{
if(root==NULL)
return root;
if(data<root->data)
root->lchild=deleteBST(root->lchild,data);
else if(data>root->data)
root->rchild=deleteBST(root->rchild,data);
else if(root->lchild!=NULL && root->rchild!= NULL)
{
root->data=findMin(root->rchild)->data;
root->rchild=deleteBST(root->rchild,root->data);
}
else
root=(root->lchild!=NULL)?root->lchild:root->rchild;
return root;
}
三、代码
#include<bits/stdc++.h>
const int N=7; //插入查找树数组长度
using namespace std;
/* 二叉查找树 操作*/
typedef int Elemtype;
typedef struct BSTNode
{
Elemtype data;
struct BSTNode *lchild,*rchild;
}BSTNode,*PNode;
//查找结点,树中存在结点值为data的结点返回true,否则返回false
bool SearchBST(PNode T,Elemtype data)
{
if(T==NULL)
return false;
if(data<T->data)
return SearchBST(T->lchild,data);
else if(data>T->data)
return SearchBST(T->rchild,data);
else
return true;
}
//向树中插入节点,若此节点在不在树中则插入,已在树中则不插入
PNode insertBST(Elemtype data,PNode root)
{
if(root==NULL)
{
root=new BSTNode();
root->data = data;
root->lchild = NULL;
root->rchild = NULL;
//printf("%d插入树中\n",data);
return root;
}
if(data < root->data)
root->lchild=insertBST(data,root->lchild);
else if(data > root->data)
root->rchild=insertBST(data,root->rchild);
return root;
}
//查找二叉查找树中最大、最小节点值;从根节点开始查找左儿子,
//只要存在左儿子就一直查找,终点就是最小的元素,最大的为右儿子查找终点
PNode findMin(PNode root)
{
if(root==NULL)
return NULL;
else if(root->lchild==NULL)
return root;
return findMin(root->lchild); //递归查找
}
PNode findMax(PNode root)
{
if(root!=NULL) //非递归查找
while(root->rchild!=NULL)
root=root->rchild;
return root;
}
//删除一个结点:如果是叶结点则直接删除;
//如果结点有一个孩子,则直接用该结点父节点连接此结点孩子结点,删除此节点;
//如果结点有两个孩子结点,则用其右子树的最小数据代替该结点的数据并递归的删除那个最小结点,因为右子树的
//最小结点不可能有左儿子因此第二次删除比较容易
PNode deleteBST(PNode root,Elemtype data)
{
if(root==NULL)
return root;
if(data<root->data)
root->lchild=deleteBST(root->lchild,data);
else if(data>root->data)
root->rchild=deleteBST(root->rchild,data);
else if(root->lchild!=NULL && root->rchild!= NULL)
{
root->data=findMin(root->rchild)->data;
root->rchild=deleteBST(root->rchild,root->data);
}
else
root=(root->lchild!=NULL)?root->lchild:root->rchild;
return root;
}
//中序输出:中序遍历二叉查找树可以得到原关键字有序序列
void print(PNode root)
{
if(root!=NULL)
{
print(root->lchild);
printf("%d ",root->data);
print(root->rchild);
}
}
int main(int argc, char *argv[]) {
Elemtype data[N] = {45,24,53,45,12,24,90};
int i;
PNode root = NULL; //二叉查找树根节点
for(i=0;i<N;i++) //创建二叉查找树
{
root=insertBST(data[i],root);
}
print(root);
printf("\n");
//查找最小值
PNode Min=findMin(root);
printf("最小值为:%d\n",Min->data);
//查找最大值
PNode Max=findMax(root);
printf("最大值为:%d\n",Max->data);
//插入节点
root = insertBST(55,root);
print(root);
printf("\n");
//删除节点24
root = deleteBST(root,24);
print(root);
printf("\n");
return 0;
}