二叉排序树(Binary Sort Tree) ,又称为二叉查找树。它或者是一棵空树,或者是具有下列性质的二叉树。
1、若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
2、若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
3、它的左、右子树也分别为二叉排序树。
总之每一个结点都满足下面条件: 左值 < 根值 < 右值
目的不是为了排序,而是为了提高查找和插入删除关键字的速度。
在仔细的介绍代码之前,光看这种结构,也能感受出,有点像二分那样,每次都可以省掉左子树或者右子树(但左右子树个数不一定相同),从而提高查找速度
『结点结构』
typedef int TElemType;
typedef struct BiTNode //结点结构
{
TElemType data; //结点数据
struct BiTNode *lchild,*rchild; //左右孩子指针
}BiTNode , *BiTree;
① 二叉排序树查找操作
/*
递归查找二叉排序树T是否存在key
@param T二叉排序树,key要找的值
@param f 指向T的双亲,初始调用值为NULL
@return success 返回 指针p指向 数据元素结点, 返回TRUE
error 返回 指针p指向 查找路径最后一个节点,返回FALSE */
Status SearchBST(BiTree T, int key , BiTree f, BiTree *p ){
if(!T){ //查找不成功
*p = f;
return FALSE;
}else if( key == T->data ){ //查找成功
*p = T;
return TRUE;
}else if( key < T->data ){
return SearchBST( T->lchild, key, T , p );//左子树继续查找
}else {
return SearchBST( T->rchild, key, T , p );//右子树继续查找
}
}
【解释】递归查找,类似二分,与key相等则返回,比key小走左边,比key大走右边。(从左到右,从小到大)
62
↙ ↘
58 88
↙ ↙ ↘
47 73 99
↙ ↘ ↙
35 51 93
↙ ↘ ↙ ↘
29 37 49 56
↙ ↙ ↘
36 48 50
②二叉排序树插入操作
/*
当二叉树排序树T中不存在关键字等于 key 的数据元素时,
插入key 并返回TRUE,否则返回FALSE */
Status InsertBST(BiTree *T, int key){
BiTree p,s;
if( ! SearchBST(*T, key, NULL, &p)){ //查找不成功
s = (BiTree) malloc (sizeof(BiTNode));
s->data = key;
s->lchild = s->rchild = NULL;
if(!p){ // (1)连根结点都没有
*T = s;
}else if(key < p->data){ // (2)小于根 放左子树
p->lchild = s;
}else { // (3)大于根 放右子树
p->rchild = s;
}
return TRUE;
}else{
return FALSE; // 树中已有关键字相同的结点
}
}
【解释】插入时,先查询元素是否存在,存在就不插入了。
★找完之后,p已经是最接近,且最适合,且就是要插入点要插入的地方。
(1)这个是给第一个点设立的,如果连一个根节点都没有,那就新建一个根节点;【插入 62 的时候】
(2)如果小于根,那就插在左子树,因为要遵循,左子树小于根,根小于右子树;
(3)如果大于根,那就插在右子树,因为要遵循,左子树小于根,根小于右子树。
62
↙ ↘
58 88
↙ ↙ ↘
47 73 99
↙ ↘ ↙
35 51 93
↙ ↘ ↙ ↘ ↘
29 37 49 56 95
↙ ↙ ↘
36 48 50
【插入一个新节点 95 】
一开始先查找元素在不在树里,key = 95 ,从62开始找,62 > 95,走右边 到88 ....再走99,再走93,发现到头了,返回没找到
没找到?那就插入一个新的结点吧。那插在93的左边还是右边呢。
遵循左子树小于根,根小于右子树,就插在右子树吧。就插入成功了。
③二叉排序树删除操作
/*
若二叉排序树T中存在关键字等于key的数据元素时,则删除该数据元素结点
并返回TRUE;否则返回FALSE */
Status DeleteBST(BiTree *T,int key){
if(!*T){ //找到最后没有关键字等于key的数据元素
return FALSE;
}else{
if(key == (*T)->data){ //找到key
return Delete(T);
}else if(key < (*T)->data){ //小于根 找左边
return DeleteBST(&(*T)->lchild , key);
}else { //大于根 找右边
return DeleteBST(&(*T