二叉搜索树
二叉搜索树是为了解决动态查找问题而提出来的,也叫做二叉排序树或二叉查找树。
基本概念
二叉搜索树(BST, Binary Search Tree):一棵二叉树,可以为空;如果不为空,则要满足以下性质:
非空左子树的所有键值小于其根结点的键值
非空右子树的所有键值大于其根结点的键值
左、右子树都是二叉搜索树
对二叉搜索树进行中序遍历,即可得到有序的数列
抽象数据类型描述
类型名称:二叉搜索树
数据对象集:一棵二叉树,对于树中每个结点X,它的左子树中所有关键字值小于X的关键字值,而它的右子树中所有关键字值大于X的关键字值
操作集:BST是SearchTree类型,X是ElementType类型
- Position Find(SearchTree BST, ElementType X):从二叉搜索树BST中查找元素X,返回其所在结点的位置
- Position FindMin(SearchTree BST):从二叉搜索树BST中查找并返回最小元素所在结点的位置
- Position FindMax(SearchTree BST):从二叉搜索树BST中查找并返回最大元素所在结点的位置
- SearchTree Insert(SearchTree BST, ElementType X):把元素X插入到二叉搜索树BST中
- SearchTree Delete(SearchTree BST, ElementType X):把元素X从二叉搜索树BST中删除
查找操作
递归形式
Position Find(SearchTree BST, ElementType X){
if(BST=NULL)
return NULL;
if(X<BST->Data)
return Find(BST->Left,X); //尾递归
else if(X>BST->Data)
return Find(BST->Right,X);
else
return BST;
}
迭代形式,执行效率较高
Position Find(SearchTree BST, ElementType X){
while(BST){
if(X>BST->Data)
BST=BST->Right;
else if(X<BST->Data)
BST=BST->Left;
else
return BST;
}
return NULL;
}
查找最大最小元素
最大元素一定在树的最右分支的端结点上,而最小元素一定在树的最左分支的端结点上。
递归实现
Position FindMin(SearchTree BST){
if(!BST)
return NULL;
else if(BST->Left==NULL)
return BST;
else
return FindMin(BST->Left);
}
Position FindMax(SearchTree BST){
if(!BST)
return NULL;
else if(BST->Right==NULL)
return BST;
else
return FindMax(BST->Right);
}
迭代实现
Position FindMin(SearchTree BST){
if(BST)
while(BST->Left!=NULL)
BST=BST->Left;
return BST;
}
Position FindMax(SearchTree BST){
if(BST)
while(BST->Right!=NULL)
BST=BST->Right;
return BST;
}
插入
二叉搜索树的插入操作,可以采用与Find类似的方法,确定插入位置
SearchTree Insert(SearchTree BST, ElementType X){
if(BST==NULL){ //原树为空,则先创建一棵树,生成一个结点
BST=(SearchTree)malloc(sizeof(struct TNode));
BST->Data=X;
BST-Left=BST->Right=NULL;
}
else{
if(X<BST->Data)
BST->Left=Insert(BST->Left,X); //递归插入左子树
else if(X>BST->Data)
BST->Right=Insert(BST->Right,X); //递归插入右子树
//else X在树中已存在,则什么都不做
}
return BST;
}
删除
删除一个元素,要考虑三种情况:
- 要删除的是叶结点:直接删除,再修改其父结点指针,置为NULL
- 要删除的结点只有一个孩子结点:将其父结点的指针指向要删除的孩子结点
- 要删除的结点有左、右两颗子树:用右子树的最小元素或者左子树的最大元素替代被删除结点
SearchTree Delete(SearchTree BST, ElementType X){
Position tmp;
if(BST==NULL)
printf("要删除的元素未找到\n");
else{
if(X<BST->Data)
BST->Left=Delete(BST->Left,X); //从左子树递归删除
else if(X>BST->Data)
BST->Right=Delete(BST->Right,X); //从右子树递归删除
else{ //找到了要被删除元素的位置
if(BST->Left&&BST->Right){ //被删除结点有两个子节点
tmp=FindMin(BST->Right); //找到右子树的最小元素
BST->Data=tmp->Data; //替代被删除结点
BST->Right=Delete(BST->Right,BST->Data); //删除右子树的最小元素
}
else{ //被删除结点有一个或零个子结点
tmp=BST;
if(BST->Left==NULL) //只有右孩子或无子结点
BST=BST->Right;
else //只有左孩子
BST=BST->Left;
free(tmp);
}
}
}
return BST;
}