二叉查找树
-
定义:又称为是二叉排序树(Binary Sort Tree)或二叉搜索树。
二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
1) 若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
2) 若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
3) 左、右子树也分别为二叉排序树;
4) 没有键值相等的节点。
-
特色:1.对二叉排序树中序遍历便可得到有序数列(相当于对数组进行二叉排序)
2. 二叉查找树的高度决定了二叉查找树的查找效率。
-
顾名思义二叉排序保证有序,它可不跟 '老婆饼' 一样狡猾 So,建立·插入·删除时都要有序
-
---------------------------------相关操作 -------------------------------
(1)查找:
这里介绍两种方式 ----> a.递归查找 :运用的是尾递归,可将为递归函数改为迭代函数
Tree FindNode(Tree root,Elemtype e){
if(root==NULL){
return NULL; //查找失败
}
if(e<root->data){ //如果查找值<当前节点值,就去他的左子树继续查找
FindNode(root->lchild,e);
}
else if(e>root->data){ //如果查找值>当前节点值,就去他的右子树继续查找
FindNode(root->rchild,e);
}
else{
printf("\n已找到罪犯节点\n");
return root; //如果e刚好等于当前节点值 就返回当前节点
}
}
b.非递归(迭代查找)
Tree Find(Tree root,Elemtype e){
while(root){
if(e<root->data){ //如果查找值<当前节点值,就向左子树移动
root=root->lchild;
}
else if(e>root->data){ //如果查找值>当前节点值,就向右子树移动
root=root->rchild;
}
else{
printf("已找到罪犯节点");
return root; //如果e刚好等于当前节点值 就返回当前节点
}
}
return NULL;
}
(2) 查找最大最小节点
( 这里也是两种<迭代&&递归>方式 )
【注】最左(右)边的节点就是整棵二叉排序树的最小(大)节点
/递归查询最左(小)节点
Tree Findmin(Tree root){
if(!root){
printf("\n未找到最小节点\n");
return NULL; //如果是空树就返回NULL;
}else if(!root->lchild){
return root;//最左,出口(左到没有左孩子)
}else{
return Findmin(root->lchild); //向左子树继续查找
}
}
// 迭代查询最右(大)节点
Tree Findmax(Tree root){
if(root){
while(root->rchild){
root=root->rchild;
}
}
return root;
}
(3)插入节点
【注】(先查找节点的合适位置,要记得返回插入位置!)
步骤: 1. 若当前的二叉查找树为空,则插入的元素为根节点;
2.若插入的元素值小于根节点值,则将元素插入到左子树中;
3.若插入的元素值不小于根节点值,则将元素插入到右子树中。
Tree InsertNode(Tree &root,Elemtype e){
if(!root){
//创建新节点
root=(Tree)malloc(sizeof(Tnode));
root->data=e;
root->lchild=root->rchild=NULL;
}
else{ //找插入位置
if(e< root->data){
root->lchild=InsertNode(root->lchild,e);
}
else if(e> root->data){
root->rchild=InsertNode(root->rchild,e);
}
}
return root;
}
(4)删除节点


分析: 1.若删除节点为叶子节点 直接删除节点,再修改父节点指针
2.若删除节点p为单支节点,让p的子树与p的父节点相连,删除p即可
3.若删除节点有左右孩子,就比较麻烦,有两种解决方案 :
a.用有右子数的最小节点代替删除节点
b.用左子树的最大节点代替删除节点
Tree DeleteNode(Tree &root,Elemtype e){
Tree tmp;
if(!root){
printf("\n未找到删除节点\n");
}
else if(e<root->data){ //若e<当前节点数值就去左子树递归删除
DeleteNode(root->lchild,e);
}else if(e>root->data){ //若e>当前节点数值就去右子树递归删除
DeleteNode(root->rchild,e);
}else //若找到删除节点
{
if(root->lchild && root->rchild)// 如果是双孩子节点
{
tmp=Findmin(root->rchild);//tmp暂时保存右子数最小节点
root->data=tmp->data; //数据替换
root->rchild=DeleteNode(root->rchild,root->data);//再去右子数删除那个最小节点
}
else{
tmp=root;
if(!root->lchild){ //若是只有右孩子的单支节点
root=root->rchild;
}else if(!root->rchild){ //若是只有左孩子的单支节点
root=root->lchild;
}
free(tmp);
}
}
return root;
}
(4)创建二叉排序树
-
创建的过程就是不断地递归插入节点
void CreateFindTree(Tree &root){
Elemtype data[7] = {45,20,53,48,12,21,90};
for(int i=0;i<7;i++){
InsertNode(root,data[i]);
}
}
(5)中序遍历(输出有序序列)
void print(Tree root)
{
if(root!=NULL)
{
print(root->lchild);
printf("%d ",root->data);
print(root->rchild);
}
}
测试程序(AC):
#include<stdio.h>
#include<malloc.h>
#define N 100
typedef int Elemtype;
//定义
typedef struct Tnode{
Elemtype data;
struct Tnode *lchild,*rchild;
}Tnode,*Tree;
int main(){
int e; Tree T=NULL,p;
CreateFindTree(T);
print(T);
p=FindNode(T,20); //p=Find(T,20);
printf(",数据是%d\n",p->data);
DeleteNode(T,20);
print(T);
p=Findmin(T);
printf("\n最小节点的数据是%d\n",p->data);
p=Findmax(T);
printf("\n最大节点的数据是%d\n",p->data);
}
-
运行结果:
-
正经致谢: